BABYRE 【攻防世界】 Reverse
题目
丢进Exeinfo PE里面,得到64bit,无壳
丢进IDA pro(x64)里面,找到主函数
代码中有一个花指令:*(unsigned int (__fastcall **)(char *))judge)(input)
unsigned int (__fastcall **)(char *)
:这是一个函数指针类型,指向一个接受char *
类型参数并返回unsigned int
类型的函数。__fastcall
是一种调用约定,它指定了函数参数传递的方式。(*)
:这表示函数指针的间接引用,即对函数指针judge
进行解引用,获取其指向的函数。(char *)judge
:这是对函数指针judge
的解引用,将其当作一个函数调用,并传递input
作为参数。- 因此,
(*(unsigned int (__fastcall **)(char *))judge)(input)
的整体含义是:调用judge
指向的函数,传递input
作为参数,并期望该函数返回一个unsigned int
类型的值
双击judge追踪看看,有的大佬说会双击跟踪不了报错,我的可以双击跟踪
一开始我还没发现有问题,以下内容参考大佬wp
选中public judge,按C,跳出“Directly convert to code?”-->Yes,变成了汇编
把红色区域全部框选起来,按P,试图重新生成function——这里会出现一个红色错误endp ; sp-analysis failed
打开IDA的Options--->General-->Disassembly,勾选“Stack pointer”,打开堆栈指针
发现出现负值,说明我的IDA7.7存在指针错误
我看几个大佬的wp,他们都没有去解决这个指针问题,可能是不影响解题吧,所以我也没去管它
这里放上解决错误的资料:IDA出现"sp-analysis failed"和F5(反编译)失败-CSDN博客
视线回到主函数,在第8行,judge是一个数组,但是在第12行,judge是一个函数指针
从二进制机器码的角度看,可以理解成这个judge函数的每个字节都被异或了
用人话说,这个函数被加密了
解决方式也是参考大佬的wp——使用IDApython脚本解决:file-->script command
大佬的脚本如下:
1 add=0x600b00 2 for i in range(182): 3 PatchByte(add+i,Byte(add+i)^0xC)
但是,我运行会报错,我的IDA没有这个函数,导入了ida_bytes
模块也没有用
放下我这边能运行的代码(记得左下角Scripting language选python):
1 import idaapi 2 3 add = 0x600b00 4 for i in range(182): 5 idaapi.patch_byte(add + i, idaapi.get_byte(add + i) ^ 0xC)
- idaapi.patch_byte函数用于修改指定地址的字节,它接受两个参数:地址和要写入的字节值。
- idaapi.get_byte函数用于获取指定地址的字节值,它接受一个参数:地址,并返回该地址处的字节值
按一次就可以了,变成下面这样:
选中judge,按C(变成汇编),框选地址B00~BB5,也就是所有的红色区域,按P(重新生成function)
此时可以在左边找到judge函数内容
点进去,F5反汇编
这个代码不难理解,写逆向脚本也不难,但是我这里又犯了一个错
我以为只需要拿v2去异或解题,v3虽然也在代码中,但是后面都没再提及了,我以及单纯就是干扰,或者是没有用的乱码数据
我只用v2运行解题脚本的时候,结果就是一个:flag
我看到这个老开心了,证明我的代码是没有错误的,思路大方向也是没有错误了,但是之后就没有找到其他的东西了
看来看去,还是v3最可疑,单独用v3运行解密脚本,是一堆没有价值可读性的东西
后面看了大佬的脚本,要把v2与v3加在一起
啊?这是为什么??代码里没有体现啊????然后我就去找了资料
双击v2,点进去看看栈
双击v3,也是看看栈
20~1C:5个,刚好对的上v2的长度
1B~13:9个,也刚好对的上v3的长度
有没有发现,v2和v3用的是一块连续的空间啊啊啊
修改后的脚本如下:
1 s1 = "fmcd" 2 s2=chr(0x7F) 3 s3="k7d;V`;np" 4 key=s1+s2+s3 5 input_str = "" 6 7 for i in range(len(key)): 8 input_str += chr(ord(key[i]) ^ i) 9 10 print(input_str)
运行结果: flag{n1c3_j0b}