源碼如下
#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