tracedump
single application IP packet sniffer
|
00001 /* 00002 * Copyright (C) 2011-2012 IITiS PAN Gliwice <http://www.iitis.pl/> 00003 * Author: PaweÅ‚ Foremski <pjf@iitis.pl> 00004 * Licensed under GNU GPL v. 3 00005 */ 00006 00007 #include <stdbool.h> 00008 #include <stdint.h> 00009 #include <sys/socket.h> 00010 #include <linux/net.h> 00011 #include <netinet/in.h> 00012 #include <stdarg.h> 00013 00014 #include "tracedump.h" 00015 00016 int32_t inject_socketcall(struct tracedump *td, struct pid *sp, uint32_t sc_code, ...) 00017 { 00018 /* int 0x80, int3 */ 00019 unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 }; 00020 char backup[4]; 00021 struct user_regs_struct regs, regs2; 00022 int ss_vals, ss_mem, ss; 00023 va_list vl; 00024 enum arg_type type; 00025 uint32_t sv; 00026 void *ptr; 00027 uint8_t *stack, *stack_mem; 00028 uint32_t *stack32; 00029 int i, j; 00030 00031 /* 00032 * get the required amount of stack space 00033 */ 00034 ss_vals = 0; 00035 ss_mem = 0; 00036 va_start(vl, sc_code); 00037 do { 00038 type = va_arg(vl, enum arg_type); 00039 if (type == AT_LAST) break; 00040 sv = va_arg(vl, uint32_t); 00041 00042 /* each socketcall argument takes 4 bytes */ 00043 ss_vals += 4; 00044 00045 /* if its memory, it takes additional sv bytes */ 00046 if (type == AT_MEM_IN || type == AT_MEM_INOUT) { 00047 ss_mem += sv; 00048 ptr = va_arg(vl, void *); 00049 } 00050 } while (true); 00051 va_end(vl); 00052 ss = ss_vals + ss_mem; 00053 00054 /* 00055 * backup 00056 */ 00057 ptrace_getregs(sp, ®s); 00058 memcpy(®s2, ®s, sizeof regs); 00059 ptrace_read(sp, regs.eip, backup, sizeof backup); 00060 00061 /* 00062 * write the stack 00063 */ 00064 stack = mmatic_zalloc(td->mm, ss); 00065 stack32 = (uint32_t *) stack; 00066 stack_mem = stack + ss_vals; 00067 00068 va_start(vl, sc_code); 00069 i = 0; j = 0; 00070 do { 00071 type = va_arg(vl, enum arg_type); 00072 if (type == AT_LAST) break; 00073 00074 sv = va_arg(vl, uint32_t); 00075 00076 if (type == AT_VALUE) { 00077 stack32[i++] = sv; 00078 } else { /* i.e. its a memory arg */ 00079 stack32[i++] = regs.esp - ss_mem + j; 00080 00081 /* copy the memory */ 00082 ptr = va_arg(vl, void *); 00083 memcpy(stack_mem + j, ptr, sv); 00084 j += sv; 00085 } 00086 } while (true); 00087 va_end(vl); 00088 00089 ptrace_write(sp, regs.esp - ss, stack, ss); 00090 00091 /* 00092 * write the code and run 00093 */ 00094 regs2.eax = 102; // socketcall 00095 regs2.ebx = sc_code; 00096 regs2.ecx = regs.esp - ss; 00097 00098 ptrace_write(sp, regs.eip, code, sizeof code); 00099 ptrace_setregs(sp, ®s2); 00100 ptrace_cont(sp, 0, true); 00101 00102 /* 00103 * read back 00104 */ 00105 ptrace_getregs(sp, ®s2); 00106 ptrace_read(sp, regs.esp - ss_mem, stack_mem, ss_mem); 00107 00108 va_start(vl, sc_code); 00109 do { 00110 type = va_arg(vl, enum arg_type); 00111 if (type == AT_LAST) break; 00112 00113 sv = va_arg(vl, uint32_t); 00114 if (type == AT_VALUE) continue; 00115 00116 ptr = va_arg(vl, void *); 00117 if (type == AT_MEM_IN) continue; 00118 00119 memcpy(ptr, stack_mem, sv); 00120 stack_mem += sv; 00121 } while (true); 00122 va_end(vl); 00123 00124 /* restore */ 00125 ptrace_write(sp, regs.eip, backup, sizeof backup); 00126 ptrace_setregs(sp, ®s); 00127 00128 mmatic_free(stack); 00129 00130 return regs2.eax; 00131 } 00132 00133 void inject_escape_socketcall(struct tracedump *td, struct pid *sp) 00134 { 00135 struct user_regs_struct regs; 00136 00137 /* make backup */ 00138 ptrace_getregs(sp, ®s); 00139 memcpy(&sp->regs, ®s, sizeof regs); 00140 00141 /* update EBX so it is invalid */ 00142 regs.ebx = 0; 00143 ptrace_setregs(sp, ®s); 00144 00145 /* run the invalid socketcall and wait */ 00146 ptrace_cont_syscall(sp, 0, true); 00147 00148 /* -> now the process is in user mode */ 00149 } 00150 00151 void inject_restore_socketcall(struct tracedump *td, struct pid *sp) 00152 { 00153 /* int 0x80, int3 */ 00154 unsigned char code[4] = { 0xcd, 0x80, 0xcc, 0 }; 00155 char backup[4]; 00156 struct user_regs_struct regs2; 00157 00158 /* backup */ 00159 ptrace_read(sp, sp->regs.eip, backup, 4); 00160 00161 /* exec */ 00162 sp->regs.eax = sp->regs.orig_eax; 00163 ptrace_setregs(sp, &sp->regs); 00164 ptrace_write(sp, sp->regs.eip, code, 4); 00165 ptrace_cont(sp, 0, true); 00166 00167 /* read the return code */ 00168 ptrace_getregs(sp, ®s2); 00169 sp->regs.eax = regs2.eax; 00170 00171 /* restore */ 00172 ptrace_setregs(sp, &sp->regs); 00173 ptrace_write(sp, sp->regs.eip, backup, 4); 00174 }