tracedump
single application IP packet sniffer

inject.c

Go to the documentation of this file.
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, &regs);
00058         memcpy(&regs2, &regs, 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, &regs2);
00100         ptrace_cont(sp, 0, true);
00101 
00102         /*
00103          * read back
00104          */
00105         ptrace_getregs(sp, &regs2);
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, &regs);
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, &regs);
00139         memcpy(&sp->regs, &regs, sizeof regs);
00140 
00141         /* update EBX so it is invalid */
00142         regs.ebx = 0;
00143         ptrace_setregs(sp, &regs);
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, &regs2);
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 }
 All Data Structures Files Functions Variables Enumerations Enumerator Defines