目标程序
程序下载:Splish
解压密码:9unk
任务目标:分析 Name/Serial 部分的算法,并写出注册机程序。
观察程序
算法分析
加载 Splish,断在入口点。
查看程序使用的 API,并对 GetWindowTextA 设置断点
继续运行程序
执行到返回,此时数据已经存到缓冲区。
我们继续跟踪到数据窗口
对数据设置内存访问断点
继续运行程序,此时停在了另一个 GetWindowTextA API 处。
我们 “F9” 继续运行,然后执行返回,可以看到缓冲区存储的是 Name
我们继续单步步过,此时程序在比较和跳转指令处
我们双击跳转指令,看看是跳转到哪里。
可以看到此时程序跳转到了 MessageBox 处,消息是 “please enter your name”,由此可以断定上面的比较跳转是在判断 name 是否为空。
我们继续执行程序,可以看到上面这段指令是在初始化寄存器,然后 esi 指向 “9unk”、edi 指向空值、ecx 存储 0xA
我们开始分析下面的循环部分的指令,第一个指令是把 name 的第一个字节存储到 eax 中
1 | cdq // 把 edx 扩展为 eax 的最高位,也就是说 eax 由 32 位扩展到了 64 位 |
现在 eax 的值是 edx + eax = 00000000 00000039
1 | idiv ecx // eax/ecx 商存储在 eax 中,余数存储在 edx 中 |
现在商是 0x5,余数是 0x7
1 | xor edx, ebx // edx 异或 ebx |
1 | mov byte ptr ds:[edi+ebx*1], dl // dl 存到 [edi + ebx * 1] |
1 | inc ebx // ebx + 1 |
这一段主要就是判断循环是否结束
循环结束后,看一下 name 计算后的值是 “09080406”
总结 name 计算步骤:(((name%0xA) xor ebx) + 0x2)-0xA;ebx 每次循环加 1;如果 name > 0xA,name = name - 0xA
我们继续向下执行,可以看到下面是计算 password 的循环
1 | movsx eax, byte ptr ds:[esi+ebx*1] |
可以看到 password 计算部分就是:password % A
1 | inc ebx |
判断循环是否结束
最后看一下循环结束的结果是:”090001020304”
总结 password 计算步骤:password % 0xA
我们循环结束后,后面是 jmp 指令,双击查看跳转的位置。可以看到这又是一个循环,这段循环应该是在计算比较正确的 serial 。
我们继续步过运行程序,首先 password 的计算结果存到 esi 中,name 的计算结果存到 edi 中。
dword 值得是 2 个字,也就是 4 个字节。也就是说 password 的计算结果实际上是获取的 “09000102” 。现在比较的值应该是 name:”09080406” 和 password:”09000102”
1 | cmp ebx, dword ptr ds:[0x00403463] |
正常循环结束,就跳出循环,弹出正确信息
1 | movsx eax, byte ptr ds:[edi+ebx*1] // 把 password 传到 eax |
第一次循环两个值相等
第二次循环值就不相等了
现在已经知道了计算的方法,我们先计算用户名 9unk 的 serial
1 | 31 % 0xA = 09 1 |
注册机编写
- (((name%0xA) xor ebx) + 0x2)-0xA;ebx 每次循环加 1;如果 name > 0xA,name = name - 0xA
- password % 0xA
1 | /* |
reference
- 本文标题:x64dbg-算法分析二.md
- 本文作者:9unk
- 创建时间:2020-12-29 01:48:12
- 本文链接:https://9unkk.github.io/2020/12/29/x64dbg-suan-fa-fen-xi-er/
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!