源码如下
#include <sys/ptrace.h>
int main()
{
int i=0;
if(ptrace(PTRACE_TRACEME,0,0,0)<0)
{
printf("failed\n");
return 0;
}
printf("succ\n");
i=1;
return 0;
}
gcc -g -o ptrace ptrace.c
一般情况下只能使用一次ptrace[PTRACE_TRACEME]。因此如果调试器在这之前使用ptrace,那么我们的调用就会返回false,于是就能知道还有其他东西在控制程序了。以前做注入进程的时候遇到进程已被注入,只能放弃尝试,现在受到这篇连接的启发
http://blog.jobbole.com/77311/和同事 曾xb 的提示,尝试绕过ptrace保护。
默认情况如下:
[root@promote Desktop]# gdb ptrace
(gdb) start
Temporary breakpoint 1 at 0x40050c: file ptrace.c, line 5.
Starting program: /root/Desktop/ptrace
Temporary breakpoint 1, main () at ptrace.c:5
5 int i=0;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.3.x86_64
(gdb) n
6 if(ptrace(PTRACE_TRACEME,0,0,0)<0)
(gdb) n
8 printf("failed\n");
(gdb) n
failed
9 return 0;
(gdb) q
A debugging session is active.
在ptrace调用处失败返回。如果做点简单的反动态调式,至此已经成功。
========================================================================
开始绕过:
过程如下,在本文连接中,作者使用.gdbinit脚本设置捕捉事件catch syscall ptrace。 当触发ptrace调用时,程序停下。作者同时修改寄存器set ($eax)=1 绕过了if判断,but,我一直没有成功。反正gdbinit中的命令和gdb本身一致,我就搓一点手动修改吧:
L6下断点,运行/启动程序,断下来后,disassemble
gdb ptrace
(gdb) b 6
Breakpoint 1 at 0x400513: file ptrace.c, line 6.
(gdb) start
Temporary breakpoint 2 at 0x40050c: file ptrace.c, line 5.
Starting program: /root/Desktop/ptrace
Temporary breakpoint 2, main () at ptrace.c:5
5 int i=0;
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.132.el6_5.3.x86_64
(gdb) c
Continuing.
Breakpoint 1, main () at ptrace.c:6
6 if(ptrace(PTRACE_TRACEME,0,0,0)<0)
(gdb) disassemble
Dump of assembler code for function main:
0x0000000000400504 <+0>: push %rbp
0x0000000000400505 <+1>: mov %rsp,%rbp
0x0000000000400508 <+4>: sub $0x10,%rsp
0x000000000040050c <+8>: movl $0x0,-0x4(%rbp)
=> 0x0000000000400513 <+15>: mov $0x0,%ecx
0x0000000000400518 <+20>: mov $0x0,%edx
0x000000000040051d <+25>: mov $0x0,%esi
0x0000000000400522 <+30>: mov $0x0,%edi
0x0000000000400527 <+35>: mov $0x0,%eax
0x000000000040052c <+40>: callq 0x400410 <ptrace@plt>
0x0000000000400531 <+45>: test %rax,%rax
0x0000000000400534 <+48>: jns 0x400547 <main+67>
0x0000000000400536 <+50>: mov $0x400658,%edi
0x000000000040053b <+55>: callq 0x4003f0 <puts@plt>
0x0000000000400540 <+60>: mov $0x0,%eax
End of assembler dump.
然后在 0x000000000040052c <+40>: callq 0x400410 <ptrace@plt> 处下断点,
b * 0x000000000040052c
执行到0x0000000000400531时,开始比较rax,此时rax值-1
(gdb) ni
0x0000000000400531 6 if(ptrace(PTRACE_TRACEME,0,0,0)<0)
(gdb) info registers rax
rax 0xffffffffffffffff -1
此处手动修改rax让程序跳转到成功返回即L11:set ($rax)=1
(gdb) set ($rax)=1
(gdb) ni
0x0000000000400534 6 if(ptrace(PTRACE_TRACEME,0,0,0)<0)
(gdb) n
11 printf("succ\n");
程序已经绕过ptrace。
不知道这算不算成功绕过,为此验证gdb是否仍工作,尝试读写内存变量i:
(gdb) p i
$1 = 0
(gdb) p &i
$2 = (int *) 0x7fffffffe23c
(gdb) x /8xb 0x7fffffffe23c
0x7fffffffe23c: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
变量i的值还能读到,再试试写
(gdb) set *(0x7fffffffe23c)=1
(gdb) x /8xb 0x7fffffffe23c
0x7fffffffe23c: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
(gdb) p i
$3 = 1
i的值由开始时0变为1,由此判断gdb应该有效,初步认为算是绕过了ptrace