【发布时间】:2020-04-30 20:12:26
【问题描述】:
我正在编写一个使用 ptrace 显示指令的 C 程序。这是代码:
#include<stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <string.h>
void run_target()
{
ptrace(PTRACE_TRACEME, 0, 0, 0);
execl("./test", "test", NULL);
}
void debugger(pid_t pid)
{
int status;
wait(&status);
while(WIFSTOPPED(status))
{
struct user_regs_struct regs;
ptrace(PTRACE_GETREGS, pid, 0, ®s);
long instruction = ptrace(PTRACE_PEEKTEXT, pid, regs.rip, 0);
ptrace(PTRACE_SINGLESTEP, pid, 0, 0);
//EDITED SO IT PRINTS ONLY LINES I WANT
if(((regs.rip >> (8*5)) & 0xFF) != 0x7f) //i noticed all the junk lines that shouldnt be there, their regs.rip began with 7f
printf("%llx %16lx\n", regs.rip, instruction);
wait(&status);
}
}
int main()
{
pid_t pid;
pid = fork();
if(pid == 0)
{
run_target();
}
else
{
debugger(pid);
}
return 0;
}
但输出看起来像这样
...
7f3bf1487308 8348da7426fa8348
7f3bf148730c d47408fa8348da74
7f3bf148730e 8d48d47408fa8348
7f3bf1487312 16ad50d8d48d474
7f3bf14872e8 18c0834810508b48
7f3bf14872ec 48f2014c18c08348
7f3bf14872f0 8948c33948f2014c
7f3bf14872f3 860f118948c33948
7f3bf14872f6 fff670860f118948
7f3bf14872f9 508bfffff670860f
而 objdump -d 看起来像这样:
000000000000064a <main>:
64a: 55 push %rbp
64b: 48 89 e5 mov %rsp,%rbp
64e: 48 8d 3d af 00 00 00 lea 0xaf(%rip),%rdi # 704 <_IO_stdin_used+0x4>
655: b8 00 00 00 00 mov $0x0,%eax
65a: e8 c1 fe ff ff callq 520 <printf@plt>
65f: 48 8d 3d a5 00 00 00 lea 0xa5(%rip),%rdi # 70b <_IO_stdin_used+0xb>
666: b8 00 00 00 00 mov $0x0,%eax
66b: e8 b0 fe ff ff callq 520 <printf@plt>
670: b8 00 00 00 00 mov $0x0,%eax
675: 5d pop %rbp
676: c3 retq
677: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1)
67e: 00 00
例如,运行 ./program | grep "64e" 会显示这一点
7f46f3bb64e2 89483e8b48f90148
7f46f3bb64e5 8b483989483e8b48
7f46f3bb64e8 48087e8b48398948
7f46f3bb64eb 48c70148087e8b48
7f46f3bb64ef 4808798948c70148
7f46f3bb7318 f64ee8ef894c9174
7f46f3bb731a f64ee8ef894c
7f46f3bb731d 4887eb0000f64ee8
7f46f3800b70 4864e889481f8948
7f46f3800b73 2504334864e88948
55dfb208464e b8000000af3d8d48
7f46f38564e2 89440af883481476
7f46f38f2a11 4334864e8458b48
7f46f380505a e264e8ff894c0874
这个实际上是正确的:
55dfb208464e b8000000af3d8d48
那么 objdump 中是否缺少某些内容,或者我的代码中是否缺少某些内容,它显示的 rip 比应有的更多?
编辑:添加整个代码
编辑:编辑了 printf,现在它打印了它应该打印的行,但它仍然在开头添加了随机十六进制 应该是什么
64a: 55
它是什么
56160a60a64a 9f3d8d48e5894855
我明白为什么指令不一样,这不是我的问题,我的问题是为什么 regs.rip 不是 64a,而是 64a。每次我重新运行程序时,开始的随机十六进制都是不同的。
【问题讨论】:
-
次要:建议
printf("%llx %16lx\n", regs.rip, instruction);以获得更好的指令对齐。 -
@bruno 是的,我在同一个程序上同时执行 objdump 和 ptrace(其中只有 2 个 printf)
-
@bruno PTRACE_TRACEME 和 PTRACE_SINGLESTEP 都返回 0 并且 PTRACE_PEEKTEXT 返回指令
-
@bruno 如果我在打印时没有放 %llx,那么编译器会警告我应该这样做
-
@qlabfgerkaSmurf 您看到的输出是有道理的,我可能有答案,但为了确保我需要更多信息。展示你在孩子身上所做的事情(即 C 代码)。添加minimal reproducible example 是最好的主意,否则回答只是令人不快的猜测。另外,请说明您使用的是哪个发行版 (
lsb_release -a) 和您的 libc 版本 (apt-cache policy libc6)。