yosigear的だいありぃ0

絶対巨人主義大学院生の書く日記

子プロセスにシステムコールを発行させる

2007-05-16 22:13:05 | コンピュタ話
#include <sys/types.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <signal.h>
#include <stdio.h>
#include <linux/user.h>
#include <stdlib.h>


char* str= "0123456789";
char* str2= "AbCdEfGhIj\n";
// unsigned long intInstr[] = {0xcd, 0x80};
unsigned long intval = 0xcc;

int main(int argc, void** argv)
{
pid_t pid;

if((pid = fork()) == -1)
{ // error
perror("fork");
} else if(pid == 0)
{ // child
ptrace (PTRACE_TRACEME, 0, 0, 0);
if (kill(getpid(), SIGSTOP) == -1) // 自分を停止
{
perror("kill");
exit(1);
}
__asm__ ("int3"); // <- int3は実行されるからeipを外から進めなくてよい
// __asm__ ("mov %eax,%cr3"); // <- これは実行されずに SIGSEGV がいくから eip を外から進める必要がある
printf("<<<<< Child End.>>>>>\n");
fflush(stdout);

exit(0);

} else
{ // parent
int st;
struct user_regs_struct regs0, regs1;
char inst[] = {0xcd, 0x80};
unsigned long getval;

if ((wait (&st)) != pid) // ptrace trace me
{ // error
fprintf(stderr, "wait error!");
exit(1);
}

ptrace (PTRACE_CONT, pid, 1, 0); // INT3
if ((wait (&st)) != pid)
{ // error
fprintf(stderr, "wait error!");
exit(1);
}

// 子プロセスのレジスタ状態、
ptrace (PTRACE_GETREGS, pid, 0, ®s0);
getval = ptrace (PTRACE_PEEKDATA, pid, regs0.eip, 1);
printf("[eip(=%08xH)] = %08xH\n",regs0.eip, getval);

// CD 80 CC 00 == INT 0x80; INT3 (注1)
ptrace (PTRACE_POKEDATA, pid, regs0.eip, 0x00cc80cd);

regs1 = regs0;
regs1.eax = 4; // write's sys-number
regs1.ebx = 1; // arg0 // stdout
regs1.ecx = (unsigned long) str2; // arg1 // target string
regs1.edx = 12; // arg2 // length str2
// regs1.esi = // arg3
// regs1.edi = // arg4

// 子プロセスに INT 0x80 を実行してもらう
ptrace (PTRACE_SETREGS, pid, 0, ®s1);
ptrace (PTRACE_CONT, pid, 1, 0);
wait(); // 自分の書いた INT3 (注1) によりストップ
printf("is WRITE SYSTEM CALL executed ?\n");fflush(stdout);

// 子プロセスのメモリを元に戻して、実行を続けさせてやる
ptrace (PTRACE_POKEDATA, pid, regs0.eip, getval);
ptrace (PTRACE_SETREGS, pid, 0, ®s0);
getval = ptrace (PTRACE_PEEKDATA, pid, regs0.eip, 1);
printf("[eip(=%08xH)] = %08xH\n",regs0.eip, getval);
ptrace (PTRACE_CONT, pid, 1, 0);

wait(); // 子プロセスの終了を待つ
printf("parent ... child ... DONE.\n");
fflush(stdout);

}
}

最新の画像もっと見る