本题是dark ctf Reverse的第二题:HelloWorld,网址:https://ctf.darkarmy.xyz/challs 题目描述:taking small Bites of Bytes
因为把文件放进IDA里分析的时候出现了和Rev/so_much 这题的文件一样的警告。因此,这里我仍然选用的ghidra进行逆向分析。 main函数中,需要用户在命令行执行时输入两个参数:argv[1]和argv[2]。然后通过check函数分别对两个参数进行检查,只有当check函数都返回0时,才能通过。
跟进check函数看一下。参数arg2表明要检查的arg1是argv[1]还是argv[2]。
如果arg2为1,则检查argv[1];如果arg2为2,则检查argv[2] 然后在while循环中对s1进行赋值,最后将s1与arg1进行比较。对于arg2==1的情况: var_48h 作为索引,初始值为0, 范围是[0, 4]。在while循环中:
dVar1 = pow(&var_40h + var_48h * 4), *(undefined8 *)0x2040); sprintf(s1 + var_48h, 0x2038, (int32_t)dVar1, s1 + var_48h);sprintf函数主要功能是把格式化的数据写入某个字符串中: int sprintf(char *string, char *format [,argument,...]);
s1 + var_48h 就是对s1字符串的每个位置进行赋值,那么0x2038应该是 %c,赋的值就是dVar1。
ok,那dVar1怎么得到的?根据ghidra的分析,是调用了一个pow函数。第一个参数是 var_40h + var_48h * 4 ,第二个参数是 *(undefined8 *)0x2040 。但是第二个参数我没找到具体的内容是啥。感觉还是得上动态调试看一下。
> x/16xb 0x00002040 - offset - 0 1 2 3 4 5 6 7 8 9 A B C D E F 0123456789ABCDEF 0x00002040 00 00 00 00 00 00 e0 3f 01 1b 03 3b 54 00 00 00 .......?...;T...两种动态调试的思路:
从main函数来看,其实,输入的参数只是为了保证能通过check函数,进入到print()函数,这个print()函数应该是打印出flag的。因此,用户输入是啥其实没必要去分析,只需要用动态调试,修改strcmp的返回值,然后直接跳到 print()函数运行即可。既然最后是在check函数里比较生成的字符串与用户输入是否相等,那只要动态调试,运行到strcmp传参的时候,就能知道用户的正确输入应该是啥了。我这里采用的是这种方法。 gef➤ set args 123 456 gef➤ b check Breakpoint 1 at 0x14c5 gef➤ rcheck函数里,最终debug到strcmp语句时,s1的值为H3ll0 ,因此用户输入的第一个参数为H3ll0
继续调试第二个参数:
gef➤ set args H3ll0 456 gef➤ r可以得到第二个参数应该为:W0rld
运行程序,得到flag为:darkCTF{4rgum3nts_are_v3ry_1mp0rt4nt!!!}
$ ./hw H3ll0 W0rld darkCTF{4rgum3nts_are_v3ry_1mp0rt4nt!!!}安装的时候可能会出现bison未安装啊,M4未安装等报错。如果报错了,就分别安装2和3中的命令进行安装即可。
需要注意的是,如果安装完后回过头去安装glibc时提示bison版本太低等问题,就根据INSTALL文件中提示的版本安装:https://ftp.gnu.org/gnu/bison/bison-2.7.tar.gz 也可以直接sudo apt-get install bison。但是安装完以后还是报错
不过我在我的kali 2020.2上是可以运行的。。所以就直接在本地的kali上调试了。
这个比赛的文件每次用IDA打开都会报错,网上说是需要修复plt表。先开个坑,啥时候有时间研究一下