前言
最近看群里有人在讨论今年的巅峰极客,说有道逆向题考的linux的反调试出的挺好的,借着这道题学习一下linux反调试
分析
- 第一个反调试
ptrace
函数,代码如下1
2
3
4
5
6
7
8
9
10
11
12if ( ptrace(0, 0LL, 1LL, 0LL) >= 0 )
'''
else
v6 = 10000000;
do
{
sleep(1u);
--v6;
}
while ( v6 );
exit(-1);
}
ptrace
函数的相关介绍可以参考官方介绍ptrace,这道题的ptrace
绕过的方法很简单,直接nop
相关跳转即可:
1 | // 修改前 |
- 第二个反调试是监控程序执行的时间:
1 | v4 = time(0LL); |
同样nop
掉即可
1 | //修改前 |
- 后面的反调试可以通过使用ida把如下的数据转化为代码(程序有部分花指令,导ida初始化会反编译出错)
1 | .text:00000000004009C4 dd 48EBEBEBh |
同样是监控代码执行的反调试,直接patch
1 | //修改前 |
第四个反调试是通过
getppid
和getsid
实现的1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22//修改前
.text:0000000000400A94 call _getpid
.text:0000000000400A99 mov edi, eax ; pid
.text:0000000000400A9B call _getsid
.text:0000000000400AA0 mov r13d, eax
.text:0000000000400AA3 call _getppid
.text:0000000000400AA8 cmp r13d, eax
.text:0000000000400AAB jnz loc_400C5B
//修改后
.text:0000000000400A94 call _getpid
.text:0000000000400A99 mov edi, eax ; pid
.text:0000000000400A9B call _getsid
.text:0000000000400AA0 mov r13d, eax
.text:0000000000400AA3 call _getppid
.text:0000000000400AA8 cmp r13d, eax
.text:0000000000400AAB nop
.text:0000000000400AAC nop
.text:0000000000400AAD nop
.text:0000000000400AAE nop
.text:0000000000400AAF nop
.text:0000000000400AB0 nop最后一个反调试同样是通过监控代码执行时间实现的
1 | //修改前 |
有几段花指令,特征就是:
call $+5
dec eax;inc eax
jmp short near
比如第一段call $+5
,如下
1 | .text:00000000004009A9 call $+5 |
可以通过分析或者调试定位到跳转地址,直接jmp就好
调试
处理了反调试之后,gdb可以直接调试,字符处理的主要逻辑通过func3
,func2
,func1
,三个函数实现,过程相对复杂,不过通过对0x400C04
下断点,可以清晰的获得我们输入的数据加密后的结果,以及要比较的对象
如下所示,我们知道字符的长度为19
1 | 0x400bf4 <main+916>: jmp 0x400c04 <main+932> |
用来比较的字符串如下
1 | gdb-peda$ x /20wx $rsp+0x50 |
我们输入abcdefghijklmnopqrs
生成的数据如下
1 | gdb-peda$ x /20wx 0x7fffffffdf60 |
通过分析输入的数据和输出的数据,能够猜到func3
,func2
,func1
三个函数可能是对输入做了某种移位处理,编写代码进行测试
1 | s=[0x69,0x70,0x67,0x6d,0x6a,0x61,0x6f,0x62,0x6e,0x71,0x63,0x64,0x68,0x6b,0x6c,0x72,0x66,0x73,0x65] |
成功获得flag
1 | ⚙ jcxp@ubuntu ~/ctf/dianfengjike python a.py |