一直在研究逆向,可是从来没有接触过Linux程序的逆向,这两天做CTF遇到了一道Linux的程序,作为一个契机,我也算是踏上了Linux程序的逆向道路。
1.静态分析
题目来源:http://daka.whaledu.com:9999/challenges#入门语言
这个程序是运行在Linux-64环境下的。
分析的第一步自然是拖进IDA,程序很简单,没有加壳,main()函数也成功识别出来了:
图片1.png (120.88 KB, 下载次数: 69)
2018-8-16 14:31 上传
查看一下字符串,看到“Incorrect password!”的字符串:
图片2.png (20.81 KB, 下载次数: 53)
2018-8-16 14:31 上传
查看引用字符串的函数,我们立即能定位到关键函数:
图片3.png (97.02 KB, 下载次数: 58)
2018-8-16 14:32 上传
程序流程很清晰,程序获取输入,然后调用sub_4006FD进行一些运算,根据运算情况判断输入是否正确;
我们重点要分析的就是sub_4006FD:
图片4.png (142.37 KB, 下载次数: 56)
2018-8-16 14:32 上传
我们可以按F5直接查看反汇编伪代码:
图片5.png (18.29 KB, 下载次数: 67)
2018-8-16 14:32 上传
但是这里的伪代码有一些错误,我们仍然要结合汇编代码进行分析。
这段程序从字符串'DufhbmfpG`imosewUglpt'中取字符进行简单的操作得到一个字符(把它叫做新字符),然后取输入字符串中的一个字符,新字符与输入字符进行比较。
字符的比较,是使用如下指令进行的:
.text:0000000000400787 sub edx, eax
.text:0000000000400789 mov eax, edx
.text:000000000040078B cmp edx,1
edx中存放的是新字符,eax是输入的字符。
正确的输入满足edx-eax=1,为了获取正确的输入,我们需要知道edx的值,我们需要逆向出计算edx的算法,这需要花费很长时间。如果是动态调试,我们直接下个断点就可以能够获取edx的值了,省时又省脑子,接下来,我们使用动态调试分析程序。
目前,笔者掌握的Linux程序动态调试的工具有三个:gbd、Radare2、IDA。
很多人推荐使用gdb,但是笔者实在不喜欢。。。笔者就不介绍gdb了,网上教程也是很多的。
接下来,就分别介绍一下如何使用Radare2和IDA动态调试Linux程序。
2.Radare动态调试
Radare2是一款开源的逆向工程平台,里面包括很多小工具,它可以反汇编、调试、分析和操作二进制文件,我们进行动态调试用的最多的是r2工具。
Radare2里的一些基本的命令:
r2 -d 文件名/线程号 ;加载文件
db 0x8048920 ; 在 0x8048920 处设置一个断点
db -0x8048920; 删除断点
dc ; 运行程序(相当于F9)
dm ; show process maps 显示进程内存映射
dr eax; 查看eax寄存器的值
dr eax=33 ; 设置寄存器d 值
pd 5 ; 查看5行汇编代码
wx 123456 @ 0x8048300在0x8048300处修改字节位1123456
wa jmp 0x8048320 @ 0x8049100 在0x8049100处写入指令jmp 0x8048320
基础知识介绍完了,正式开始调试。
首先使用r2 -d r100加载程序,然后使用pd 20命令,查看当前的汇编代码,查看20行:
图片6.png (473.42 KB, 下载次数: 46)
2018-8-16 14:32 上传
我们可以看到,当前程序RIP的值是0x7f991d23dca0,这里看着像是linux库的加载地址,而不是程序自身的加载地址。这里是系统在加载程序时初始化的一些操作,一直运行到0x7f991d23dce4 jmp r12;才跳到程序真正的入口。
使用db 0x7f991d23dce4命令在0x7f991d23dce4处下断点,使用dc命令运行到该位置;
图片7.png (284.42 KB, 下载次数: 62)
2018-8-16 14:32 上传
查看r12,的确和IDA里显示的程序入口点相同:
图片8.png (16.84 KB, 下载次数: 63)
2018-8-16 14:32 上传
接下来,我们就可以结合IDA,在关键函数位置(0x4007E8)下断点了,但是如果我们直接在0x4007E8处下断点并运行程序,就会发现程序没有弹出“Enter the password:”的字符串,程序跑飞了。
这个程序使用了一些反调试的手段,0x4005D0处的跳转会根据程序的运行环境不同而跳转到不同位置:
图片9.png (32.22 KB, 下载次数: 61)
2018-8-16 14:32 上传
我们修改这里的代码,使其跳转到0x4007E8(main函数)。
使用wa命令将0x40005d0处的指令修改为jmp 0x4007e8:
图片10.png (113.01 KB, 下载次数: 58)
2018-8-16 14:32 上传
这个时候我们继续运行程序就能进入main函数过程了。
结合IDA分析,接着我们就可以在0x400787下断点,获取每次edx的值:
图片11.png (88.1 KB, 下载次数: 66)
2018-8-16 14:32 上传
如图,我们输入的第一个字符是‘0’,但是edx的值是0x44(‘D’),由此可以判断,我们第一次输入‘C’,才能通过验证。
接下来继续运行程序,程序就会弹出错误提示,无法进行第二个字符的比较了,为了防止这中情况,我们将0x40078e处的je跳转修改为jne跳转,接着继续运行程序,我们获取到edx的值是0x70,那么第二个应该输入的字符就应该是“o”
图片12.png (243.15 KB, 下载次数: 59)
2018-8-16 14:32 上传
这样就可以计算出要输入的值了,最后得到flag:Code_Talkers。
3.IDA动态调试
本题也可以使用IDA进行动态调试。
IDA要比Radare2友好的多,毕竟是图形化界面。使用IDA动态调试Linux程序,需要一个windows系统和一个Linux系统,通过远程调试的方式在windows上调试linux程序。
在windows上安装IDA,从IDA安装目录下将dbgsrv\linux_server(linux_server64)复制到linux中,然后启动linux_server:
图片13.png (48.79 KB, 下载次数: 48)
2018-8-16 14:32 上传
linux_server启动,在23946端口监听,接下来在windows中打开IDA,设置远程调试:
图片14.png (44.17 KB, 下载次数: 68)
2018-8-16 14:32 上传
设置参数:
图片15.png (20.36 KB, 下载次数: 56)
2018-8-16 14:32 上传
点击OK,就可以进行动态调试了,IDA直接来到程序入口点
图片16.png (20.23 KB, 下载次数: 52)
2018-8-16 14:32 上传
接下来就可以F7/F8单步调试了,这里仍然需要绕过反调试的点,使用的方式是来到main函数入口,右键,设置IP:
图片17.png (70.68 KB, 下载次数: 72)
2018-8-16 14:32 上传
然后在0x400787下断点,依次获取edx的值,计算要输入的值,调试思路和Radare2中的思路相同,这里就不详细介绍了。
图片18.png (2.75 KB, 下载次数: 62)
2018-8-16 14:32 上传
OK,本文完!