170617 逆向-CrackMe之024
1625-5 王子昂 总结《2017年6月17日》 【连续第258天总结】
A.CrackMe(24)
B.这个CM做了好几天了,第一次见到自己修改自己指令的判断,还是挺懵的
放到PEiD里监测显示是MASM,纯汇编写的程序能玩的花样就比编译器制造的多得多了
首先在OD中运行,总是跳到奇奇怪怪的命令里去
尝试放到IDA中反汇编,只出现了窗口相关的代码,在最后只知道进入了某个函数中进行处理,却完全没有相关代码
没办法,只好回到OD中单步跟
004012E9 .^ 74 EE je short Chafe_2.004012D9 ; 关键跳
004012EB > 68 59304000 push Chafe_2.00403059 ; /Your serial is not valid.
很明显NOP掉关键跳是不行的,观察004012D9的代码发现都不是指令,显然简单的修改为jmp也是不行的
再往下看
00401301 . 68 73 30 40 0>ascii "hs0@",0 ; YES! You found your serial!!
00401306 . FF35 5C314000 push dword ptr ds:[0x40315C] ; |hWnd = 16A4312E ('Your serial is not valid.',class='Edit',parent=11283162)
0040130C . E8 67010000 call <jmp.&USER32.SetWindowTextA> ; \SetWindowTextA
00401311 . 33C0 xor eax,eax
00401313 . C9 leave
00401314 . C2 1000 retn 0x10
这里是正确提示,那么jmp 00401301试试,爆破成功
注册机
首先是将name的每4个字节的ASCII累加,循环16次,再加上固定数0x58455443
然后将结果加上Serial转化成INT型的值
跟着继续看: 004012BB . 3105 D9124000 xor dword ptr ds:[0x4012D9],eax
这一行命令与常见的不同,它修改的是指令的值(而不是寄存器或是存储变量区域的值)
接下来会运行到D9的命令,因此这个地方很关键
那么应该修改成什么样呢?暂且不管,看下面的未经修改的命令是什么:
004012CB . BE EC114000 mov esi,Chafe_2.004011EC
004012D0 . B9 3E000000 mov ecx,0x3E
004012D5 . 33DB xor ebx,ebx
004012D7 . EB 04 jmp short Chafe_2.004012DD
004012D9 > 54 push esp ; 改变
004012DA 45 db 45 ; CHAR 'E'
004012DB 58 db 58 ; CHAR 'X'
004012DC 00 db 00
004012DD > AD lods dword ptr ds:[esi] ; 跳转到这里
004012DE . 33D8 xor ebx,eax
004012E0 . 49 dec ecx ; user32.76C946F6
004012E1 .^ 75 FA jnz short Chafe_2.004012DD ; 从4011EC到4011EC+0x3E,每个4字节与bx异或
004012E3 . 81FB FBCFFCAF cmp ebx,0xAFFCCFFB ; 结果若为0xAFFCCFFB则成功
004012E9 .^\74 EE je short Chafe_2.004012D9 ; 关键跳
最终关键跳前方是将ebx与一个数比较,相等则跳至004012D9
那么再看ebx怎么来的,lods指令是将esi处的数据送至eax中,那么这个循环的功能就很明显了:
从4011EC到4011EC+0x3E,每个4字节与bx异或
既然比较成功了跳的是4012D9,那么很明显,4012D9处的指令应该被修改为跳至成功提示的指令
直接修改试试,爆破成功。并且此时可以看到,4012D9的机器码为EB 26
之后4012DB和DC的机器码就应该由最终的异或判断确定了
由于异或的逆运算还是异或,即只要将结果与一个运算数异或就能得到另一个运算数
观察确认会改变的机器码只有4012D9-4012DC的4个字节,也就是4012D8开始的后三个字节和4012DC的第一个字节
将4011EC到4011D4的机器码全部复制下来
刨掉这两个四字节,将前后两部分数据分别异或,脚本为:
a=[0x55,0x8B,0xEC,0x83,0xC4,0xFC,0x8B,0x45,0x0C,0x83,0xF8,0x10,0x75,0x0D,0x6A,0x00,0xE8, 0x6B,0x02,0x00,0x00,0x33,0xC0,0xC9,0xC2,0x10,0x00,0x83,0xF8,0x0F,0x75,0x0E,0x8B, 0x45,0x08,0xE8,0x18,0x01,0x00,0x00,0x33,0xC0,0xC9,0xC2,0x10,0x00,0x83,0xF8,0x01, 0x75,0x06,0x33,0xC0,0xC9,0xC2,0x10,0x00,0x3D,0x11,0x01,0x00,0x00,0x0F,0x85,0xE7, 0x00,0x00,0x00,0x8B,0x45,0x14,0x3B,0x05,0x60,0x31,0x40,0x00,0x75,0x1A,0x6A,0x00, 0x68,0x96,0x30,0x40,0x00,0x68,0xA7,0x30,0x40,0x00,0xFF,0x75,0x08,0xE8,0x17,0x02, 0x00,0x00,0x33,0xC0,0xC9,0xC2,0x10,0x00,0x3B,0x05,0x58,0x31,0x40,0x00,0x74,0x0C, 0x3B,0x05,0x54,0x31,0x40,0x00,0x0F,0x85,0xAE,0x00,0x00,0x00,0xC7,0x05,0xD9,0x12, 0x40,0x00,0x54,0x45,0x58,0x00,0x6A,0x00,0x8D,0x45,0xFC,0x50,0x6A,0x64,0xFF,0x35, 0x50,0x31,0x40,0x00,0xE8,0xBC,0x01,0x00,0x00,0x83,0x7D,0xFC,0x00,0x74,0x5F,0x50, 0x6A,0x14,0x68,0x6C,0x31,0x40,0x00,0xFF,0x35,0x54,0x31,0x40,0x00,0xE8,0xAF,0x01, 0x00,0x00,0x85,0xC0,0x74,0x48,0xA1,0x0B,0x30,0x40,0x00,0xBB,0x6C,0x31,0x40,0x00, 0x03,0x03,0x43,0x81,0xFB,0x7C,0x31,0x40,0x00,0x75,0xF5,0x5B,0x03,0xC3,0x31,0x05, 0xD9,0x12,0x40,0x00,0xC1,0xE8,0x10,0x66,0x29,0x05,0xD9,0x12,0x40,0x00,0xBE,0xEC, 0x11,0x40,0x00,0xB9,0x3E,0x00,0x00,0x00,0x33,0xDB,0xEB] f=0 s=0 x=0 for i in a: s=s+i*(2**(f*8)) if(f==3): x=x^s f=0 s=0 else: f=f+1
print(hex(x))
得到结果:0xa213fcee
再与最后一部分的值0x81fa7549和最终结果0xAFFCCFFB异或,得到:
0x8c15465c
这就是中间两个四字节04 xx xx xx || xx ad 33 d8异或的结果
那么中间四个字节怎么求呢?由于我们之前已经推算出004012D9的机器码必须为EB 26,因此前两个xx就已知了
而因为异或是按位的,因此虽然运算数是两个四字节,但四字节的高低位之间可以单独对应进行异或,即:
04 eb 26 xx
xx ad 33 d8
异或得到
5c 46 15 8c
则5c和04异或可以得到第一个xx,为58
8c和d8异或可以得到最后一个xx,为54
这样就得到了中间的修改结果:eb 26 54 58
再向上逆推,NAME处理后的值+SERIAL整型值(设为X),与原004012D9的值异或,再减去X的高四位,得到0x585426eb
原004012D9的值是0x00584554
整理算法,X^0x00584554-X的高四位=0x585426eb
同理,由于异或是按位的,因此可以将四字节数值拆分单独进行异或
由于0x585426eb加的是一个四位数,因此高四位必然是0x5854(或进位为0x5855,下面说),那么只需要与运算数0x00584554的高四位进行异或就能得到X的高四位了,运算得0x580c
PS:如果将高四位当做0x5855,异或得到0x580d,验算0x580d+0x26eb并不会进位,因此舍去这种情况
那么第四位26eb+0x580c的结果与X的第四位异或应该等于0x4554
逆运算得0x3ba3
这样就能得到X=0x45543ba3了
这样只要用X-NAME处理后的值就能得到SERIAL了
事实上,由于基准数0x58455443是大于最终结果0x45543ba3的,因此肯定要出现超出32位寄存器取值范围的情况,这种时候由于python是不会自动进行调整的,因此需要自己在脚本中修正
脚本为:
s=input()+chr(0)*20 #补足字符串的长度 a=0x58455443 for i in range(16):a=a+ord(s[i])+ord(s[i+1])*0x100+ord(s[i+2])*0x10000+ord(s[i+3])*0x1000000 k=0x580c3ba3-a while(k<0): #当作差后的值为负数时用补码求法来修正k=0xffffffff+k+1 print(k)
这样注册机就做成了
验证成功
C.明日计划
计算思维(如果还有的话
170617 逆向-CrackMe之024相关推荐
- [反汇编练习] 160个CrackMe之024
[反汇编练习] 160个CrackMe之024. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- 170621 逆向-CrackMe之027
1625-5 王子昂 总结<2017年6月21日> [连续第262天总结] A. CrackMe B. 大概了解了一下ELF文件,Linux平台下的可执行文件,使用终端可以执行 在win平 ...
- 170604 逆向-CrackMe之013
1625-5 王子昂 总结<2017年6月3日> [连续第245天总结] A.CrackMe(13) B.中间几个的难度是三星和???--吓到我了,完成第一页以后再去挑战这几个吧 第13个 ...
- 170527 逆向-CrackMe(4)
1625-5 王子昂 总结<2017年5月27日> [连续第238天总结] A. CrackMe(4) B. 先拖到PEiD,无壳,是Delphi 打开,是一个没有按钮的序列号验证 拖入O ...
- 170613 逆向-CrackMe之023
1625-5 王子昂 总结<2017年6月13日> [连续第254天总结] A.CrackM(19) B.PEiD显示是TASM/MASM写的,貌似是纯汇编?居然有界面 打开,没有弹窗和按 ...
- 2022DASCTF Apr X FATE 防疫挑战赛复现
misc 第二题: wireshark打开直接搜字符串flag,发现4个字段含有flag,其中一个发现是zip文件,想把它提取出来, 将他数据导入一个新的zip文件,打开 在50段找到密码加密字段,找 ...
- 逆向破解之160个CrackMe —— 023-024
CrackMe -- 023 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- IDA Pro逆向实战之Crackme(简单篇)
IDA Pro逆向实战之Crackme(简单篇) 今天手闲的很,没事就拿出了以前没解决的逆向题来做一下,具体的源程序在附件里,废话少说,直接上菜: 0. 源程序运行效果(输入不对的,直接退出): ...
- 逆向破解之160个CrackMe —— 007
CrackMe -- 007 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
最新文章
- c语言实现java接口_五分钟带你了解Java是如何从容而优雅地实现接口数据校验
- 采用傅立叶变换空间载波法从强度分布得到相位分布,即从空间上呈正弦分布的光强信息,恢复出波面的相位信息
- 2263: neighbor(贪心)
- 春春幼儿园堆积木大赛_春云边车
- inputstreamreader未关闭会导致oom_Linux内核OOM机制分析和防止进程被OOM杀死的方法...
- Windows安装mysql8.0
- Flutter AnimatedContainer 动画使用解析
- Vmware虚拟机不能使用键盘的解决方法
- 十条有用的 Go 技术
- MATLAB中一些特殊的函数
- 编译WINDOWS版FFmpeg:编译x264
- 睡眠分期--深度学习算法
- Java:List转Map (用stream实现)
- 英语常见的固定搭配有哪些
- 扫描服务Windows Image Acquisition(WIA)错误1068的解决办法
- 武大计算机导师蔡贤涛,CAD模型在线集成与离线集成关键技术研究
- 计算机网络之五:基本器件(网卡,集线器,交换机,路由器)
- 网络编程三剑客之sed
- google退出后产生的影响
- CSDN竞赛6期题解