ubuntu 에서 ptrace() 했을때
안녕 하세요..
ptrace() 에 대해서 공부 중인데
환경은 windows7 64bit 에 vmware 64bit 설치하고 ubuntu 12.04 64bit 올려서 하고 있습니다.
여기저기서 본 소스로 테스트 중인데 아래 소스중에서
ptrace(PTRACE_GETREGS, child_pid, NULL, ®s);
str = (char *)malloc((params[2]+1) * sizeof(char));
printf("Write called with " "%ld, %ld, %ld, %ld, %s \n", sc_number, regs.rbx, regs.rcx, regs.rdx, str);
다른 부분은 나오는거 같은데 regs.rcx 부분이 -1 로 나옵니다.
소스에서 regs.rcx 부분을 사용해서 str 에 데이터를 가져 오는거 같은데.. 값을 제대로 가지고 오지 못하고 있습니다.
Write called with 14, 4553904, -1, 0,
Write called with 14, 4553904, -1, 0,
Write called with 13, 7261568, -1, 140736404729224, (null)
Write called with 13, 7261568, -1, 140736404729224, (null)
Write called with 14, 4553904, -1, 7261856,
Write called with 14, 4553904, -1, 7261856,
아무리 찾아봐도 찾을수가 없네요..
그리고 bash 를 trace 걸건데 command 를 입력 하면 fork 된 command 도 trace 하고 싶습니다..
하지만 fork 된 command 를 따라 가는 방법을 모르겠네요..
혹시 방법 아시는분 알려 주세요 ^^
감사합니다.
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <asm/ptrace-abi.h>
#include <sys/reg.h>
#include <sys/syscall.h>
#define BUFFER_SIZE 1024
#define SIZEOF_LONG sizeof(long)
#ifdef __x86_64__
#define SC_NUMBER (8 * ORIG_RAX)
#define SC_RETCODE (8 * RAX)
#else
#define SC_NUMBER (4 * ORIG_EAX)
#define SC_RETCODE (4 * EAX)
#endif
const int long_size = sizeof(long);
struct user_regs_struct regs;
void getdata(pid_t child, long addr, char *str, int len)
{ char *laddr;
int i, j;
union u {
long val;
char chars[long_size];
}data;
i = 0;
j = len / long_size;
laddr = str;
while(i < j) {
data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * 8, NULL);
memcpy(laddr, data.chars, long_size);
++i;
laddr += long_size;
}
j = len % long_size;
if(j != 0) {
data.val = ptrace(PTRACE_PEEKDATA, child, addr + i * 8, NULL);
memcpy(laddr, data.chars, j);
}
str[len] = '\0';
}
static void parent(pid_t child_pid)
{
int status;
long sc_number, sc_retcode;
long sc_bx, sc_dx;
long params[3];
char *str, *laddr;
ptrace(PTRACE_ATTACH, child_pid, 0, 0);
while (1)
{
/* Wait for child status to change: */
wait(&status);
if (WIFEXITED(status)) {
printf("Child exit with status %d\n", WEXITSTATUS(status));
exit(0);
}
if (WIFSIGNALED(status)) {
printf("Child exit due to signal %d\n", WTERMSIG(status));
exit(0);
}
if (!WIFSTOPPED(status)) {
printf("wait() returned unhandled status 0x%x\n", status);
exit(0);
}
if (WSTOPSIG(status) == SIGTRAP) {
/* Note that there are *three* reasons why the child might stop
* with SIGTRAP:
* 1) syscall entry
* 2) syscall exit
* 3) child calls exec
*/
sc_number = ptrace(PTRACE_PEEKUSER, child_pid, SC_NUMBER, NULL);
//sc_retcode = ptrace(PTRACE_PEEKUSER, child_pid, SC_RETCODE, NULL);
//sc_bx = ptrace(PTRACE_PEEKUSER, child_pid, 8 * RBX,NULL);
ptrace(PTRACE_GETREGS, child_pid, NULL, ®s);
str = (char *)malloc((params[2]+1) * sizeof(char));
printf("Write called with " "%ld, %ld, %ld, %ld, %s \n", sc_number, regs.rbx, regs.rcx, regs.rdx, str);
} else {
printf("Child stopped due to signal %d\n", WSTOPSIG(status));
}
fflush(stdout);
/* Resume child, requesting that it stops again on syscall enter/exit
* (in addition to any other reason why it might stop):
*/
ptrace(PTRACE_SYSCALL, child_pid, NULL, NULL);
}
}
int main(int argc, char **argv)
{
if (argc <= 1) {
fprintf(stderr, "Usage: %s command args -or- %s -p pid\n",
argv[0], argv[0]);
exit(1);
}
if (argc >= 3 && !strcmp(argv[1], "-p")) {
pid_t pid = atoi(argv[2]);
parent(pid);
}
return 0;
}

댓글 달기