查壳
有壳
去之
IDA
主函数部分很简单,有个判断v4地址上的字符串是否等于DDCTF{reverseME}。
进入关键函数sub_401000瞅瞅:v4 v1都是地址且没说。a1是我们输入的字符的地址。中间有个do while循环,次数和字符串长度一致,预计是逐个处理。
解题
说实话,摸不着头脑,既然v1和v4的地址和内容都不给,而且byte_402FF8是空的,啥数据没有。那就只好动调了
首先是解决v4 = (const char *)(a1 - v1);
地址v4等于地址a1和v1相减,结果调出来是0x400……根本无法跳转过去。
其次我又看了下a1到v1之间的内存地址,全是空的……
迷惑,继续下一步。到了do while循环,看得出一直在给v1赋值。这里重点观察下v1:
找到地址,内存区跳转到v1处,暗中观察_(:з」∠)_
发现循环下v1确实每次都在赋值,但是搞不清哪里来的数据赋值……
循环多次后,摸清这个循环的作用是每次v1的地址+1,然后将byte_402ff8的第[v1[0x400]]的字符写道地址v1上。但是动调过程仍没有找到byte_402ff8真身,双击看到的静态地址还是空内容,如下图所示:
虽然关键字符内容没头绪,但v1的变化还是能观察到的,多次尝试后发现每次输入后v1的值变化都不一样。
考虑到这个函数的返回值并没有用上,而且地址v4和地址v1有联系。我直接输入DDCTF{reverseME}进行动调测试:
打开程序输入该乱码,依旧闪退。投降……
flag
看了别人的wp,日了狗了,flag真就那串乱码(ノ`Д)ノ
不过仍旧不知道为啥这就是flag……
flag{ZZ[JX#,9(9,+9QY!}
坑&填坑
1.v1到底是如何被赋值的
脚本逻辑就是在这里面找DDCTF{reverseME}里每个字符对应的位置,然后转字符串输出。不知道为啥……
2.为什么主函数声明的地址v4和sub_40100声明的地址v4是同一个地址
ida动调看到的byte数据在八个ff之前和别人的从OD里挖出来的不一样,后面的倒是相同。
3.看到别人的wp还有一种做法是在od里dump处byte_402FF8的值,然后就可以写脚本操作
byte_402FF8的地址就是0x402FF8,是我脑子瓦特了……