00001 #include <sys/ptrace.h>
00002 #include <sys/types.h>
00003 #include <sys/wait.h>
00004 #include <sys/user.h>
00005 #include <asm/unistd.h>
00006 #include <signal.h>
00007 #include <unistd.h>
00008 #include <errno.h>
00009 #include <string.h>
00010 #include "process-trace.h"
00011
00012 ProcessTrace::ProcessTrace()
00013 {
00014 before_syscall = false;
00015 replace_call = false;
00016 stopped = false;
00017 }
00018
00019 std::string ProcessTrace::ChildOnFork()
00020 {
00021 ptrace(PTRACE_TRACEME, 0, NULL, NULL);
00022 return std::string("");
00023 }
00024
00025 std::string ProcessTrace::ParentOnFork()
00026 {
00027
00028
00029 return std::string("");
00030 }
00031
00032 std::string ProcessTrace::HandleEvents()
00033 {
00034 if(stopped)
00035 return std::string("");
00036
00037 if(GetExitCode() != -1)
00038 return std::string("");
00039
00040 int status = 0;
00041 int r = waitpid(GetPID(), &status, WNOHANG);
00042
00043 if(r == -1)
00044 return std::string("waitpid failed: ") + std::string(strerror(errno));
00045
00046 if(r == 0)
00047 return std::string("");
00048
00049 if(WIFEXITED(status))
00050 {
00051 exit_code = WEXITSTATUS(status);
00052 return std::string("");
00053 }
00054
00055 if(!WIFSTOPPED(status))
00056 return std::string("");
00057
00058
00059
00060
00061
00062
00063
00064
00065 struct user_regs_struct regs;
00066 if(ptrace(PTRACE_GETREGS, GetPID(), NULL, ®s) == -1)
00067 return std::string("ptrace failed: ") + std::string(strerror(errno));
00068
00069 #if __WORDSIZE == 64
00070 if(before_syscall && HandleSyscall(regs.orig_rax, (void*)regs.rdi, (void*)regs.rsi,
00071 (void*)regs.rdx, (void*)regs.r10, (void*)regs.r8, return_code))
00072 #else
00073 if(before_syscall && HandleSyscall(regs.orig_eax, (void*)regs.ebx, (void*)regs.ecx,
00074 (void*)regs.edx, (void*)regs.esi, (void*)regs.edi, return_code))
00075 #endif
00076 {
00077
00078 replace_call = true;
00079 before_syscall = false;
00080 #if __WORDSIZE == 64
00081 regs.orig_rax = __NR_getpid;
00082 #else
00083 regs.orig_eax = __NR_getpid;
00084 #endif
00085 if(ptrace(PTRACE_SETREGS, GetPID(), NULL, ®s) == -1)
00086 return std::string("ptrace failed: ") + std::string(strerror(errno));
00087 }
00088 else
00089 {
00090 before_syscall = !before_syscall;
00091 if(replace_call)
00092 {
00093 #if __WORDSIZE == 64
00094 if((int)regs.rax != GetPID())
00095 printf("Looks like the output could not be hijacked\n");
00096 regs.rax = return_code;
00097 #else
00098 regs.eax = return_code;
00099 #endif
00100 if(ptrace(PTRACE_SETREGS, GetPID(), NULL, ®s) == -1)
00101 return std::string("ptrace failed: ") + std::string(strerror(errno));
00102 }
00103 replace_call = false;
00104 }
00105
00106 if(ptrace(PTRACE_SYSCALL, GetPID(), NULL, NULL) == -1)
00107 return std::string("ptrace failed: ") + std::string(strerror(errno));
00108 return std::string("");
00109 }
00110
00111 std::string ProcessTrace::SetChildMem(char* addr, char* buf, size_t len)
00112 {
00113 if(!pid)
00114 return std::string("No process started");
00115
00116 while(len >= sizeof(int))
00117 {
00118 if(ptrace(PTRACE_POKEDATA, GetPID(), addr, *(int*)buf) != 0)
00119 return std::string("Unable to write data: ") + std::string(strerror(errno));
00120 buf += sizeof(int);
00121 addr += sizeof(int);
00122 len -= sizeof(int);
00123 }
00124
00125 if(len)
00126 {
00127
00128 int data = ptrace(PTRACE_PEEKDATA, GetPID(), addr, NULL);
00129 if(errno != 0)
00130 return std::string("Unable to write data: ") + std::string(strerror(errno));
00131
00132 char* c = (char*)&data;
00133 while(len)
00134 {
00135 *c = *buf;
00136 c++;
00137 buf++;
00138 len--;
00139 }
00140 if(ptrace(PTRACE_POKEDATA, GetPID(), addr, data) != 0)
00141 return std::string("Unable to write data: ") + std::string(strerror(errno));
00142 }
00143
00144 return std::string("");
00145 }
00146
00147 std::string ProcessTrace::GetChildMem(char* addr, char* buf, size_t len)
00148 {
00149 if(!pid)
00150 return std::string("No process started");
00151
00152 while(len >= sizeof(int))
00153 {
00154 *(int*)buf = ptrace(PTRACE_PEEKDATA, GetPID(), addr, NULL);
00155 if(errno != 0)
00156 return std::string("Unable to read data: ") + std::string(strerror(errno));
00157 buf += sizeof(int);
00158 addr += sizeof(int);
00159 len -= sizeof(int);
00160 }
00161
00162 if(len)
00163 {
00164
00165 int data = ptrace(PTRACE_PEEKDATA, GetPID(), addr, NULL);
00166 if(errno != 0)
00167 return std::string("Unable to write data: ") + std::string(strerror(errno));
00168
00169 char* c = (char*)&data;
00170 while(len)
00171 {
00172 *buf = *c;
00173 c++;
00174 buf++;
00175 len--;
00176 }
00177 }
00178
00179 return std::string("");
00180 }
00181
00182 std::string ProcessTrace::Attach(pid_t p)
00183 {
00184 if(ptrace(PTRACE_ATTACH, p, NULL, NULL) == -1)
00185 return std::string("ptrace failed: ") + std::string(strerror(errno));
00186 pid = p;
00187 return std::string("");
00188 }
00189
00190 std::string ProcessTrace::Detach()
00191 {
00192 if(!pid)
00193 return std::string("No process started");
00194 if(ptrace(PTRACE_DETACH, GetPID(), NULL, NULL) == -1)
00195 return std::string("ptrace failed: ") + std::string(strerror(errno));
00196 pid = 0;
00197 return std::string("");
00198 }
00199
00200 std::string ProcessTrace::Stop()
00201 {
00202 if(!pid)
00203 return std::string("No process started");
00204
00205 if(stopped)
00206 return std::string("");
00207
00208 if(kill(GetPID(), SIGSTOP) == -1)
00209 return std::string("kill failed: ") + std::string(strerror(errno));
00210 stopped = true;
00211 return std::string("");
00212 }
00213
00214 std::string ProcessTrace::Continue()
00215 {
00216 if(!pid)
00217 return std::string("No process started");
00218
00219 if(!stopped)
00220 return std::string("");
00221 if(kill(GetPID(), SIGCONT) == -1)
00222 return std::string("kill failed: ") + std::string(strerror(errno));
00223 stopped = false;
00224 return std::string("");
00225 }
00226
00227 std::string ProcessTrace::GetRegisters(struct user_regs_struct *regs)
00228 {
00229 if(ptrace(PTRACE_GETREGS, GetPID(), NULL, ®s) == -1)
00230 return std::string("ptrace failed: ") + std::string(strerror(errno));
00231 return std::string("");
00232 }
00233
00234 std::string ProcessTrace::SetRegisters(struct user_regs_struct *regs)
00235 {
00236 if(ptrace(PTRACE_SETREGS, GetPID(), NULL, ®s) == -1)
00237 return std::string("ptrace failed: ") + std::string(strerror(errno));
00238 return std::string("");
00239 }
00240