Reverse~(本来说后面来把做当时做了题的wp更新下,拖太久了,那就算了,暂且就这两个题😂
find_plut0
开始我使用z3来解,掉进坑里了。
这里手动把程序中的连续的数据定义为数组,然后转换一下类型,方便直接复制到z3中使用。
但是跑不出结果,,。
接着使用了最基本的angr模板来跑一下,结果秒出:
1 | import angr, claripy, sys |
1 | WARNING | 2021-08-16 12:12:05,063 | cle.loader | The main binary is a position-independent executable. It is being loaded with a base address of 0x400000. |
这个有很多不可通过键盘输入的字符,所以使用pwntools来远程sendline一下。
1 | from pwn import * |
然后是找使用z3得不到正确结果的原因。
看了一下运算过程,首先发现了一个/运算:它在python3和C语言中有点区别,python3中会保留运算小数,C中直接取整。这里改为>>1就保持一致了。
再次跑了一下,得到仍然不是正确结果。
调试看运算过程,从汇编层面发现了问题所在,是因为计算的数据类型不当。
程序定义的输入为char类型数组,然后计算的时候也都是以char数组数类型来算的,,ida就把我从汇编层面看到的很多的当运算的数要大于127才会对计算有影响的运算在伪代码中都直接省去了(也可以说这里是ida优化太好了
但对于本题,正确的输入恰好不全是可打印字符,范围可以是(1~255),这也是程序要给nc来连接远程的原因,方便我们输入数据。
正是由于正确输入范围在1~255,所以运算过程直接看伪代码就肯定不对了,z3也得不到正确结果。
下面举几个汇编层面看到的要数据大于127才会对计算结果有影响的汇编指令:
eg1:
伪代码:
汇编代码:红框部分在伪代码中并没有体现,因为当计算的数为char范围的话,这个对最终结果也确实没有影响的。
eg2:
伪代码:
汇编代码:这可以看到伪代码中没有展示出来这里只取最低字节来移位。然后这里比较奇怪,我测试这里sar edx,cl移动的都是1位,但cl的值也不为1呀。而且按照正常cl值来移动的话又显然不对,这个地方还是比较迷糊。
eg3:
伪代码:
汇编代码:这里注意这个movsx指令(带符号扩展传送指令),它先会用al的符号位来填充eax的高24位。也就是说当我们要计算的数是大于127的话,这里结果经过传送指令后就变成了对应的负数。这个其实在运算后用&0xff取低字节后对结果不会有影响,因为一个数转化为对应的负数后他们的二进制位是没有变的。如-1*6与255*6他们计算后的低字节都是相同的。虽然这个例子不影响最后的结果,但值得注意一下。
最后,感觉本题的出题人的本意也是为了对我上面所提到的考察一下,本意上是要我们用angr要解。
main_replica
rust语言逆向,他和go一样都是无虚拟机的高级语言。
首先可以从标志字符串main.rs识别出来这是rust程序,字符串窗口也能看到很多标志字符串:
在做了这个题写wp的时候,乘着这是一个个rust题,我去搭建了一下rust的开发环境。一是为了方便自己编写玩一下rust程序;二是为了使用rust-reversing-helper这个项目来恢复rust程序中的符号。rust-reversing-helper
搭建整个环境到最后符号签名的应用遇到坑肯定还是有的,这个以后来专门开一个文章记录下。
本想wp中提一下用了这个恢复签名的效果,,结果很不理想。
然后回到我做这个题的时候。
根据elf文件的特征,找到main函数,因为程序代码量还是有点大,这就要着重去找关键代码。
很快定位到关键比较:
其实加密就是打乱输入的顺序,然后与密文比较。
调试一遍,得到映射关系就好:
1 | base = '0123456789abcdefghijklmno' |