-
-
[原创](r0_0t) 叹息之墙 writeup
-
发表于: 2018-10-1 13:14 3587
-
拿到程序之后跑一下,基本没有什么信息。
用OD打开,搜索字符串,找到了运行程序时的输出以及输入正确、错误对应的输出。
用IDA打开。。。
找到使用“输入正确”字符串的程序段,在0x44F13D。往前找,发现是用[esi+3010h]和立即数0xAD1C95B5比较,继续往前找,发现这个函数(在IDA距离视图中)上半部分实际上是一个巨大的switch(通过[esi+3010h]的不同取值分别跳往下方不同的程序段,执行完之后跳回顶端0x40A09B)。
然后接下来寻找某个程序段,在[esi+3010h]中放入了0xAD1C95B5使得程序转向显示输入正确的程序段执行,用IDA搜索这个数,找到只有0x44E753可能。
但是分析这一小段的逻辑,必须[esi+3053h]为最低位零 才可能执行到“输入正确”。寻找设置[esi+3053h]的程序段,发现还是只有一个0x44d170,比较0x401020的返回值和0x6e616b34(4kan)来设置[esi+3053h],然后这个401020函数传入的参数分别是0x65757832(2xue)、0和[esi+3024h]所指向的连续两个双字。
通过在循环开始位置断点,动调是哪一个程序段修改了此处,找到0x44C195
分析一下,发现输入的字符串的数字分割之后放在了0x49FE40数组中,然后这个0x44C195数次执行相当于从0x49F000数组中查出了以输入串的每一个数字为下标对应的值,并对它们求和。正好0x49F000这个数组大小是4*351字节(之后紧邻着2xue4kan)。
然后这个0x401020干了什么呢……查看调用列表发现__aullrem 64位的取模函数,查看调用发现取模数一直是0xFFA1CF8F,猜测这是一个类似哈希的算法。根据前面对[esi+3024h]的分析,这个函数的参数实际上是两个四字,第一个一直是0x65757832,第二个是0x44C195计算的和,动调发现调用取模函数前后主要在操作三个四字,观察它们的行为,包括平方、右移一位、求和,猜测这其实是一个快速幂取模函数。用各种参数测试一下。
发现
(0x65757832^n) % 0xffa1cf8f = 0x6E616B34
跑一个简单的脚本看看给0x401020什么参数会让结果是 ‘4kan’
得到了一组数{ 0x055121c15, 0x154b3eba3, 0x25455bb31, 0x353f78abf, 0x453995a4d, 0x5533b29db, 0x652dcf969, 0x7527ec8f7, 0x852209885, 0x951c26813};
现在的问题就是从0x49f000数组中取出最多9个数和等于上面的这一组数。分析0x49f000这个数组,发现其中的每一个数都是{ 15825810, 138348210, 252282030, 329907270, 389890410, 612684930, 857758902, 1429598170, 2144397255 }的倍数,而且恰好(比如15825810这个数的1倍到270倍全部出现在0x49f000数组中)各自出现0到{ 270, 30, 16, 12, 10, 6, 4, 2, 1 }次。而且这组数刚好是9个,于是假设输入的数据经过0x44C195正好分别对应这9个因数的倍数,跑个脚本:
这个的结果是【74 4 12 12 4 4 1 2 1】,将这个数组与d[]对应项相乘,然后转换成16进制到0x49f000查,得到的就是输入的数字了,排序之后就是序列号了
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)