拿到程序先运行了下(还是比较相信出题的大佬的),在win10系统中运行失败,放xp下运行正常,不过第二次点按钮会出错。此程序是窗口程序,输入错误注册码不提示任何信息。
拖入ida,发现入口代码被更改成错误代码,看导出除了start
还有Tls_Callbase_0
,原来用了Tls,代码如下:
先通过TEB获取自身两次,然后依次获取PEB、程序基址、PE的NT头、程序入口地址。然后调用xor_410DD6
函数将入口入的0xc8个字节与eax指向的硬编码字串循环异或。直接patch。
由于是窗体程序,且没有出错弹窗,直接查看GetDlgItemTextA,只有一处调用,说明此处一定是验证的开始。直接看伪代码:
程序的传参方式受不了,特别是后面,看得有点蒙。 这里又出现了异或的这个函数,这次参数有:地址是sub_411B30
,异或字节数是426,异或串是PEDIY
,此字串也是硬编码的,不过伪代码不知道为什么没显示出来。
异或完直接调用sub_411B30
,然后还原sub_411B30
。 下面又看了下sub_411B30
和sub_411825
,这时伪代码根本没法看了,完全看不出什么,而且里面还有些堆的申请释放等函数混杂在一起,静态看起来犹如天书。有一点看出来了,没有看到明显的比较或校验,sub_411825
中使用了VirtualAlloc
。
把sub_411B30
顺便也patch了,而且把异或函数直接ret
了,patch完了,程序再也不出错了。
OD载入程序,没有停在入口,直接运行了,无妨,直接GetDlgItemTextA
下断,输入确定后停到了预期位置。大概走了下,sub_411B30
函数对输入进行异或还有置换操作,再进行异或移位。此为第一次分析的结果。 输入先进行异或
异或后的输入进行查表置换,大概过程如代码示例:
相应的程序代码如下:
转换表为:
我顺便看了下置换表对应的输入字符,字符范围为数字+大小字母+!+@,共64个。
sub_411B30
中还调用了sub_410F75
,对转换后的结果再进行变换,变换公式为(a^0xcc<<3)|(a^0xcc>>5)
跟到这已经烦躁不行,有很多的堆函数什么的。所以就想直接看看整体过程。
然后直接进了sub_411825
,静态的时候已经发现此处有VirtualAlloc
,又翻看了下,没有明显弹窗的地方,此函数结束后就直接进入事件流程了。所以推测,弹窗在VirtualAlloc
的空间的代码中。只跟了下流程,大概是:如果sub_411975
函数返回真,则进行VirtualAlloc
,拷贝411A9C
处的0x94个字节数据,并循环与原始输入异或,最后执行代码。 只里有个细节,异或完成后,在复制过来的数据偏移0x61和0x8C处,分别加上了两个地址之间的dword偏移量,然后在数据后又加上了最后一次参加异或的输入后一位,后面就直接执行复制过来的数据了。据此猜测这两处是两个call,改的是操作数,也就是偏移,程序代码如下:
看到了这,我想偷个懒,尝试能不能直接通过代码的特点和规律,直接还原代码。先从入口,返回和那两个偏移入手。 原始的代码数据如下:
首先,入口通常为push ebp mov ebp,esp
,对应机器码为55 8B EC
,得到Bwn
再看返回,数据最后一位添加的不可能是C3
,不在可输入范围,所以A6
异或后就为C3
或C2
,所以此处的异或字符为e
或d
再看两个call,B0 2B B9 94 BD
和6D 53 6E 73
,call
的对应机器码是E8
,所以B0
对应的异或字符为X
,6D
对应k
,通常偏移是xx xx 00 00
或xx xx FF FF
,所以94 BD
对应Kb
,6E 73
对应ns
。 似乎没法进行下去了。尝试多次也不见效。继续跟踪。这次跟踪重点是进VirtualAlloc
的条件,即sub_411975
函数。
反复跟踪,终于明白,转换后的输入先转成16进制,再将此转换成4进制,最后与一串常量比较,校验的函数为sub_41612A
,主要校验是经过两轮,每轮比较0x20个四进制数。 常量串为:
那反算回来不就是key了。动手操作,发现我想到了,最后结果多处有多值。反变换脚本如下:
结果如下,前面是序号,后面为可能值:
还是上ida,用上面的xor1脚本函数,慢慢对。 结合前面已经分析的字串和此次的结果,整理下: 前三位是Bwn
比较确定;输入应该是20位,那0x60,0x63,0x64处对应的异或数XkB
应该是输入的第17、20、1位;0x8B,0x8E,0x8F处对应的异或数kns
应该是输入的第20、3、4位。条件符合。所以此时的输入串为Bwns????????????X??k
。 但是反算结果中还有个别位是唯一解的,第11位,第19位,那输入为Bwns??????y?????X?Ok
。
再看看返回,猜测返回应该是C3
而不是C2
,因为我们的输入都大于0x20,一般返回中没有这么大的偏移,所以暂定为C3
,对应输入为e
,返回的前一个应该是pop ebp
,字节码为5D
,对应异或码为P
,这两个分别对应输入的第7、8位。判定后对照反算结果,条件符合。所以此时已得到的输入为Bwns??Pe??y?????X?Ok
再往pop ebp
上面看,上面一条应该是mov esp,ebp
,与开头对应,保持栈平衡,机器码为8B E5
,异或值为At
,对应输入的第5、第6位,这样,开头的指令也比较正常。此时已得到的输入为BwnsAtPe??y?????X?Ok
。
下面就比较难看了。对照了下反解结果,第10位可选值有Pi
,但是从程序的校验码来看,20个字符各不相同,因此第10位为i
,所以此时已得到的输入为BwnsAtPe?iy?????X?Ok
。已经出现MessageBoxA
的偏移。
似乎没有特别明显的了,那从头开始试吧,第9位对应一个操作码,有三个可选值dcs
。 在函数开头,能影响一个push的值。选择d
时,push了一个函数地址,一看是cookie检验的。所以此时已得到的输入为BwnsAtPediy?????X?Ok
。出现了Pediy
,呵呵。
在411B1A
出现mov fs:30320000h, ecx
,一看偏移有问题,改成00,异或值为0x32,0x30
,分别对应输入第12,13位。所以此时已得到的输入为BwnsAtPediy20???X?Ok
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)