pic_dbg.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/ptrace.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/user.h>
#include <sys/reg.h>
void print_user_regs(struct user_regs_struct *puregs)
{
if (puregs) {
printf("-- user regs --\n");
//printf(" r15: %lld\n", puregs->r15);
//printf(" r14: %lld\n", puregs->r14);
//printf(" r13: %lld\n", puregs->r13);
//printf(" r12: %lld\n", puregs->r12);
printf(" rbp: %p\n", (void *)puregs->rbp);
//printf(" rbx: %lld\n", puregs->rbx);
//printf(" r11: %lld\n", puregs->r11);
//printf(" r10: %lld\n", puregs->r10);
//printf(" r9: %lld\n", puregs->r9);
//printf(" r8: %lld\n", puregs->r8);
printf(" rax: %lld\n", puregs->rax);
//printf(" rcx: %lld\n", puregs->rcx);
//printf(" rdx: %lld\n", puregs->rdx);
printf(" rsi: %lld\n", puregs->rsi);
printf(" rdi: %lld\n", puregs->rdi);
printf(" orig_rax: %lld\n", puregs->orig_rax);
printf(" rip: %p\n", (void *)puregs->rip);
//printf(" cs: %lld\n", puregs->cs);
//printf(" eflags: %p\n", (void *)puregs->eflags);
printf(" rsp: %p\n", (void *)puregs->rsp);
//printf(" ss: %lld\n", puregs->ss);
//printf(" fs_base: %p\n", (void *)puregs->fs_base);
//printf(" gs_base: %p\n", (void *)puregs->gs_base);
//printf(" ds: %lld\n", puregs->ds);
//printf(" es: %lld\n", puregs->es);
//printf(" fs: %lld\n", puregs->fs);
//printf(" gs: %lld\n", puregs->gs);
printf("-- ---- ---- --\n\n");
}
}
void print_user(struct user *pu)
{
if (pu) {
print_user_regs(&pu->regs);
// u_fpvalid
// i387
printf("u_tsize: %lld\n", pu->u_tsize);
printf("u_dsize: %lld\n", pu->u_dsize);
printf("u_ssize: %lld\n", pu->u_ssize);
printf("start_code: %lld\n", pu->start_code);
printf("start_stack: %lld\n", pu->start_stack);
printf("u_tsize: %lld\n", pu->signal);
// reserved
// u_ar0
// __u_ar0_word
// u_fpstate
// __u_fpstate_word
printf("u_comm: %s\n", pu->u_comm);
for (int i = 0;
i < sizeof(pu->u_debugreg)/sizeof(pu->u_debugreg[0]); i++)
printf("u_debugreg[%i]: %lld\n", i, pu->u_debugreg[i]);
}
}
int main(int argc, char *argv[])
{
pid_t cpid, w;
int status;
struct user_regs_struct uregs;
cpid = fork();
if (cpid == -1) {
perror("fork");
exit(EXIT_FAILURE);
}
if (cpid == 0) { /* Code executed by child */
printf("Child PID is %ld\n", (long) getpid());
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
char *newargv[] = { NULL, NULL, NULL, NULL };
char *newenviron[] = { NULL };
if (argc < 2) {
fprintf(stderr, "Usage: %s <file-to-exec> [args]\n", argv[0]);
exit(EXIT_FAILURE);
}
newargv[0] = argv[1];
if (argv[2])
newargv[1] = argv[2];
if (argv[3])
newargv[2] = argv[3];
execve(argv[1], newargv, newenviron);
perror("execve"); /* execve() returns only on error */
exit(EXIT_FAILURE);
} else { /* Code executed by parent */
ptrace(PTRACE_SEIZE, cpid, NULL,
PTRACE_O_EXITKILL | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT);
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
for (int i = 0; i < 15; i++) {
putchar('=');
fflush(stdout);
sleep(1);
}
puts(">");
fflush(stdout);
sleep(2);
system("clear");
#endif
/*
* wait for SIGTRAP(by execve)
*/
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSTOPPED(status)) {
#ifdef ADVERTISED_DISPLAY
puts(">> 系统调用execve");
#endif
printf("stopped by signal %d\n", WSTOPSIG(status));
printf("herein, successful calls to execve\n");
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
ptrace(PTRACE_CONT, cpid, NULL, NULL);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
#endif
/*
* wait for SIGTRAP(by asm int3 immediately after {)
*/
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSTOPPED(status)) {
#ifdef ADVERTISED_DISPLAY
puts(">> 进入sum函数");
#endif
printf("stopped by signal %d\n", WSTOPSIG(status));
printf("herein, immediately after {\n");
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
#endif
/*
* single step to next int3
*/
for (int i = 0; i < 5; i++) {
ptrace(PTRACE_SINGLESTEP, cpid, NULL, NULL);
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSTOPPED(status)) {
#ifdef ADVERTISED_DISPLAY
printf(">> 单步执行 - %d\n", i+1);
#endif
printf("stopped by signal %d\n", WSTOPSIG(status));
printf("herein, single-step %d\n", i+1);
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
#endif
}
/*
* wait for SIGTRAP(by asm int3 immediately precede })
*/
ptrace(PTRACE_SINGLESTEP, cpid, NULL, NULL);
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSTOPPED(status)) {
#ifdef ADVERTISED_DISPLAY
puts(">> 离开sum函数");
#endif
printf("stopped by signal %d\n", WSTOPSIG(status));
printf("herein, immediately precede }\n");
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
ptrace(PTRACE_CONT, cpid, NULL, NULL);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
#endif
/*
* wait for SIGTRAP(by exit_group syscall)
*/
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFSTOPPED(status)) {
#ifdef ADVERTISED_DISPLAY
puts(">> 系统调用exit_group");
#endif
printf("stopped by signal %d\n", WSTOPSIG(status));
printf("herein, exit_group syscall\n");
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
ptrace(PTRACE_CONT, cpid, NULL, NULL);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
#ifdef ADVERTISED_DISPLAY
system("sleep 2; clear");
#endif
/*
* wait for ending of debugee
*/
w = waitpid(cpid, &status, WUNTRACED | WCONTINUED);
if (w == -1) {
perror("waitpid");
exit(EXIT_FAILURE);
}
if (WIFEXITED(status)) {
#ifdef ADVERTISED_DISPLAY
puts(">> 被调试程序即将终止");
#endif
printf("exited, status=%d\n", WEXITSTATUS(status));
printf("herein, ending of debugee\n");
ptrace(PTRACE_GETREGS, cpid, NULL, &uregs);
print_user_regs(&uregs);
} else {
printf("unexpected result, quit\n");
exit(EXIT_FAILURE);
}
exit(EXIT_SUCCESS);
}
}
prog.c
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "sum.h"
int main(int argc, char *argv[])
{
int op1 = 0, op2 = 0, res = 0;
if (argc > 2)
op2 = atoi(argv[2]);
if (argc > 1)
op1 = atoi(argv[1]);
res = sum(op1, op2);
return 0;
}
sum.c
#include "sum.h"
int sum(int op1, int op2)
{
__asm__("int3");
int sum = 0;
sum = op1 + op2;
__asm__("int3");
return sum;
}
sum.h
#ifndef LTTC_SUM_H_
#define LTTC_SUM_H_
extern int sum(int op1, int op2);
#endif