170617 逆向-CrackMe之024
来源:互联网 发布:青果软件教务系统 编辑:程序博客网 时间:2024/05/14 06:57
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=0s=0x=0for 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=0x58455443for i in range(16): a=a+ord(s[i])+ord(s[i+1])*0x100+ord(s[i+2])*0x10000+ord(s[i+3])*0x1000000k=0x580c3ba3-awhile(k<0):#当作差后的值为负数时用补码求法来修正 k=0xffffffff+k+1print(k)
这样注册机就做成了
验证成功C.明日计划
计算思维(如果还有的话
- 170617 逆向-CrackMe之024
- 170531 逆向-CrackMe之007
- 170601 逆向-CrackMe之008
- 170602 逆向-CrackMe之009
- 170604 逆向-CrackMe之013
- 170604 逆向-CrackMe之014
- 170606 逆向-CrackMe之015
- 170610 逆向-CrackMe之019
- 170613 逆向-CrackMe之023
- 170619 逆向-CrackMe之033
- 170620 逆向-CrackMe之034
- 170621 逆向-CrackMe之027
- 170625 逆向-Crackme之010
- 170626 逆向-Crackme之005
- 171026 逆向-Patch(CrackMe之41)
- IDA Pro逆向实战之Crackme(简单篇)
- 序列号型CrackMe逆向之OD技巧篇
- 序列号型CrackMe逆向之IDA技巧篇
- PageHelper 分页类
- 计算经纬度之间的距离
- win7 配置 matlab Mex 环境
- JSP<include>静态引入和动态引入
- 学界 | Yann LeCun最新研究成果:可以帮助GAN使用离散数据的ARAE
- 170617 逆向-CrackMe之024
- JSP九大内置对象和JSP/Servlet作用域
- CSS 新特性之 Native Variables、 Feature Queries、Grid Layout
- 浅析Java反射机制
- Register 方法学习笔记
- 输出字符串的哈弗曼编码
- Android中内存泄漏的发生原因及优化
- 数据库性能优化之SQL语句优化
- ShardedJedisPipeline 源码分析