工具:1. 按钮事件地址转换器E2A

2. PEID

3. Ollydbg

同样我们先来运行一下这个程序,



ok按钮是被禁用的,有一个help按钮点击后弹出一个消息框:消息框显示提示信息为。本程序需要输入正确的姓名的序列号,把OK按钮和Cancella按钮隐藏显示出其后面的RingZero的LOGO

我们随便输入姓名和序列号



发现OK还是禁用的,那我们就点击Canella试试,发现没用并且序列号被清零

我们熟悉完程序后,正式开始分析。

我们还是先用PEID看看其文件信息,

发现其是用Delphi编写的32位程序,我们打开OD载入程序。

运行程序随便输入用户名和序列号



随后我们需要分析其对应的各个按钮事件,用E2A打开程序文件查看各个按钮事件对应的地址,因为OK按键被禁用所以我们先分析Cancela按钮消息,用E2A程序打开查看Cancella按钮事件的地址

然后在OD中搜索此地址并下段,然后单击CancellaClick按钮程序会停在此地址处

然后单步向下并且注意跳转指令(因为我们输入的是错误的注册码,所以程序走的肯定是不正确的分支,所以我们就和程序反着来,显式改变eip,逆其道而为之),先看看这样后能不能满足条件(如果能满足在回头来分析如何让其实现跳转)。

F8向下分析遇见一个跳转指令,按此程序其是要跳转(那么我们就逆其道而为之),显式改变eip为00442EF0,然后执行程序



发现CancellaClick按钮没了,而且OK被启用了(那么正好我们再来分析一下OK按钮),用E2A查找OK按钮的地址

在OD中搜索地址并下断点后点击OK按钮,点击后程序将停在此地址处

F8单步运行,直到遇见判断跳转指令其程序要跳转(我们就逆其道而为之),显式改变eip为00442dca后,运行程序运行程序后,程序的OK按钮也去除了(哈哈!完成任务)



下面我们就看如何能让程序实现这两个跳转,

下面我们我们先来分析一下第一处跳转(即在按CancellaClick按钮处的跳转)

重新加载程序然后运行并输入用户名和序列号,



然后点击Cancella按钮程序停在其按钮事件处理处,我们向下分析看见测试指令前面的关键函数,我们需要分析这个关键函数,F8向下运行并F7进入关键函数

分析关键函数

00442AF4  /$  55            push ebp
00442AF5 |. 8BEC mov ebp,esp
00442AF7 |. 83C4 F8 add esp,-0x8
00442AFA |. 53 push ebx
00442AFB |. 56 push esi
00442AFC |. 8955 F8 mov [local.2],edx
00442AFF |. 8945 FC mov [local.1],eax
00442B02 |. 8B45 FC mov eax,[local.1]
00442B05 |. E8 DE10FCFF call aLoNg3x_.00403BE8
00442B0A |. 33C0 xor eax,eax
00442B0C |. 55 push ebp
00442B0D |. 68 902B4400 push aLoNg3x_.00442B90
00442B12 |. 64:FF30 push dword ptr fs:[eax]
00442B15 |. 64:8920 mov dword ptr fs:[eax],esp
00442B18 |. 8B45 FC mov eax,[local.1]
00442B1B |. E8 140FFCFF call aLoNg3x_.00403A34 ; 求用户名长度
00442B20 |. 83F8 05 cmp eax,0x5 ; 用户名长度不能小于5
00442B23 |. 7E 53 jle XaLoNg3x_.00442B78
00442B25 |. 8B45 FC mov eax,[local.1]
00442B28 |. 0FB640 04 movzx eax,byte ptr ds:[eax+0x4] ; eax = 用户名的第五个字符
00442B2C |. B9 07000000 mov ecx,0x7
00442B31 |. 33D2 xor edx,edx
00442B33 |. F7F1 div ecx
00442B35 |. 8BC2 mov eax,edx
00442B37 |. 83C0 02 add eax,0x2 ; eax = eax % 7 +2
00442B3A |. E8 E1FEFFFF call aLoNg3x_.00442A20 ; 计算eax的阶乘
00442B3F |. 8BF0 mov esi,eax
00442B41 |. 33DB xor ebx,ebx
00442B43 |. 8B45 FC mov eax,[local.1]
00442B46 |. E8 E90EFCFF call aLoNg3x_.00403A34 ; 计算用户名的长度
00442B4B |. 85C0 test eax,eax
00442B4D |. 7E 16 jle XaLoNg3x_.00442B65
00442B4F |. BA 01000000 mov edx,0x1
00442B54 |> 8B4D FC /mov ecx,[local.1] ; 此循环用用户名的每一个字符乘以esi(esi为eax的阶乘),结果存在ebx中
00442B57 |. 0FB64C11 FF |movzx ecx,byte ptr ds:[ecx+edx-0x1]
00442B5C |. 0FAFCE |imul ecx,esi
00442B5F |. 03D9 |add ebx,ecx
00442B61 |. 42 |inc edx
00442B62 |. 48 |dec eax
00442B63 |.^ 75 EF \jnz XaLoNg3x_.00442B54
00442B65 |> 2B5D F8 sub ebx,[local.2] ; 用 ebx - 局部变量2
00442B68 |. 81FB 697A0000 cmp ebx,0x7A69
00442B6E |. 75 04 jnz XaLoNg3x_.00442B74 ; if(ebx == 0x7a69) ebx=1; else ebx=0
00442B70 |. B3 01 mov bl,0x1
00442B72 |. EB 06 jmp XaLoNg3x_.00442B7A
00442B74 |> 33DB xor ebx,ebx
00442B76 |. EB 02 jmp XaLoNg3x_.00442B7A
00442B78 |> 33DB xor ebx,ebx
00442B7A |> 33C0 xor eax,eax
00442B7C |. 5A pop edx
00442B7D |. 59 pop ecx
00442B7E |. 59 pop ecx
00442B7F |. 64:8910 mov dword ptr fs:[eax],edx
00442B82 |. 68 972B4400 push aLoNg3x_.00442B97
00442B87 |> 8D45 FC lea eax,[local.1]
00442B8A |. E8 290CFCFF call aLoNg3x_.004037B8
00442B8F \. C3 retn
00442B90 .^ E9 E306FCFF jmp aLoNg3x_.00403278
00442B95 .^ EB F0 jmp XaLoNg3x_.00442B87
00442B97 . 8BC3 mov eax,ebx ; ebx =eax,因为要想不跳转 al不为0,即ebx不能为0
00442B99 . 5E pop esi
00442B9A . 5B pop ebx
00442B9B . 59 pop ecx
00442B9C . 59 pop ecx
00442B9D . 5D pop ebp
00442B9E . C3 retn

if((ebx-局部变量2 )== 0x7a69) 则会使al=1从而达到目的不跳转。

而ebx是由 用户名的每一位分别乘以 ((用户名第五个字符%7+2)的阶乘)的累加

而我们需要分析局部变量2怎么来的,

mov [local.2],edx可得其是由edx得到的,再往关键函数上分析看edx是怎么得到的

00442ECC  |.  8B45 FC       mov eax,[local.1]                        ;  eax = 填写的注册码
00442ECF |. E8 9C47FCFF call aLoNg3x_.00407670 ; 将注册码变为10进制形式
00442ED4 |. 50 push eax ; 返回值入栈
00442ED5 |. 8D55 FC lea edx,[local.1]
00442ED8 |. 8B83 DC020000 mov eax,dword ptr ds:[ebx+0x2DC]
00442EDE |. E8 DD03FEFF call aLoNg3x_.004232C0
00442EE3 |. 8B45 FC mov eax,[local.1]
00442EE6 |. 5A pop edx ; 栈中值出栈到edx
00442EE7 |. E8 08FCFFFF call aLoNg3x_.00442AF4
00442EEC |. 84C0 test al,al

所以要想去掉cancella按钮,并启用OK按钮就用户名和注册码应该满足条件为

用户名的每一位分别乘以 ((用户名第五个字符%7+2)的阶乘)的累加 减去 注册码 等于0x7a69

如果用户名为987654,则注册码为204103我们重新填写并点击Cancella按钮后程序如我们所愿,

然后我们分析OK按钮事件处理的第二处判断跳转

用E2A查看OK按钮事件地址

在OD中搜索并下断点后,单击OK按钮程序会停在此地址处

F8向下运行并进入测试转移指令前的关键函数,并分析此关键函数的代码

00442BA0  /$  55            push ebp
00442BA1 |. 8BEC mov ebp,esp
00442BA3 |. 6A 00 push 0x0
00442BA5 |. 6A 00 push 0x0
00442BA7 |. 6A 00 push 0x0
00442BA9 |. 53 push ebx
00442BAA |. 56 push esi
00442BAB |. 8BF2 mov esi,edx
00442BAD |. 8945 FC mov [local.1],eax
00442BB0 |. 8B45 FC mov eax,[local.1]
00442BB3 |. E8 3010FCFF call aLoNg3x_.00403BE8
00442BB8 |. 33C0 xor eax,eax
00442BBA |. 55 push ebp
00442BBB |. 68 672C4400 push aLoNg3x_.00442C67
00442BC0 |. 64:FF30 push dword ptr fs:[eax]
00442BC3 |. 64:8920 mov dword ptr fs:[eax],esp
00442BC6 |. 33DB xor ebx,ebx
00442BC8 |. 8D55 F8 lea edx,[local.2]
00442BCB |. 8BC6 mov eax,esi
00442BCD |. E8 6E4AFCFF call aLoNg3x_.00407640
00442BD2 |. 8D45 F4 lea eax,[local.3]
00442BD5 |. 8B55 F8 mov edx,[local.2]
00442BD8 |. E8 730CFCFF call aLoNg3x_.00403850
00442BDD |. 8B45 F8 mov eax,[local.2]
00442BE0 |. E8 4F0EFCFF call aLoNg3x_.00403A34 ; 求长度
00442BE5 |. 83F8 05 cmp eax,0x5
00442BE8 |. 7E 60 jle XaLoNg3x_.00442C4A
00442BEA |. 8B45 F8 mov eax,[local.2]
00442BED |. E8 420EFCFF call aLoNg3x_.00403A34 ; 求注册码长度
00442BF2 |. 8BF0 mov esi,eax
00442BF4 |. 83FE 01 cmp esi,0x1
00442BF7 |. 7C 2F jl XaLoNg3x_.00442C28
00442BF9 |> 8D45 F4 /lea eax,[local.3] ; 此循环将 (注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41
00442BFC |. E8 0310FCFF |call aLoNg3x_.00403C04 ; 得到的字符与原字符替代保存到局部变量3中
00442C01 |. 8D4430 FF |lea eax,dword ptr ds:[eax+esi-0x1]
00442C05 |. 50 |push eax
00442C06 |. 8B45 F8 |mov eax,[local.2]
00442C09 |. 0FB64430 FF |movzx eax,byte ptr ds:[eax+esi-0x1]
00442C0E |. F7E8 |imul eax
00442C10 |. 0FBFC0 |movsx eax,ax
00442C13 |. F7EE |imul esi
00442C15 |. B9 19000000 |mov ecx,0x19
00442C1A |. 99 |cdq
00442C1B |. F7F9 |idiv ecx
00442C1D |. 83C2 41 |add edx,0x41
00442C20 |. 58 |pop eax
00442C21 |. 8810 |mov byte ptr ds:[eax],dl
00442C23 |. 4E |dec esi
00442C24 |. 85F6 |test esi,esi
00442C26 |.^ 75 D1 \jnz XaLoNg3x_.00442BF9
00442C28 |> 8B45 F4 mov eax,[local.3]
00442C2B |. 8B55 FC mov edx,[local.1]
00442C2E |. E8 110FFCFF call aLoNg3x_.00403B44 ; 比较eax 和 edx所指的字符串是否相等
00442C33 |. 75 17 jnz XaLoNg3x_.00442C4C ; if(eax == ecx) ebx = 1; else ebx = 0
00442C35 |. 8B45 FC mov eax,[local.1]
00442C38 |. 8B55 F4 mov edx,[local.3]
00442C3B |. E8 040FFCFF call aLoNg3x_.00403B44
00442C40 |. 75 04 jnz XaLoNg3x_.00442C46
00442C42 |. B3 01 mov bl,0x1
00442C44 |. EB 06 jmp XaLoNg3x_.00442C4C
00442C46 |> 33DB xor ebx,ebx
00442C48 |. EB 02 jmp XaLoNg3x_.00442C4C
00442C4A |> 33DB xor ebx,ebx
00442C4C |> 33C0 xor eax,eax
00442C4E |. 5A pop edx
00442C4F |. 59 pop ecx
00442C50 |. 59 pop ecx
00442C51 |. 64:8910 mov dword ptr fs:[eax],edx
00442C54 |. 68 6E2C4400 push aLoNg3x_.00442C6E
00442C59 |> 8D45 F4 lea eax,[local.3]
00442C5C |. BA 03000000 mov edx,0x3
00442C61 |. E8 760BFCFF call aLoNg3x_.004037DC
00442C66 \. C3 retn
00442C67 .^ E9 0C06FCFF jmp aLoNg3x_.00403278
00442C6C .^ EB EB jmp XaLoNg3x_.00442C59
00442C6E . 8BC3 mov eax,ebx ; eax = ebx, 要想让al不等于0,则ebx不能为0
00442C70 . 5E pop esi
00442C71 . 5B pop ebx
00442C72 . 8BE5 mov esp,ebp
00442C74 . 5D pop ebp
00442C75 . C3 retn

eax所指的字符串是 (注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41得到的新字符串

ebx所指的字符串为用户名。

if(eax所指的字符串 == ebx所指的字符串)
ebx=1;
else
ebx=0;

当ebx==1时,则eax也为1,不发生跳转从而使OK按钮隐藏

所以用户名等于(注册码的每一个字符乘以本身后)* 注册码长度 % 19 + 0x41得到的字符串

此时注册码为204103,其对应的用户名为 : AIMEUG

重新输入用户名点击OK后,程序如我们所愿显示出RingZero的logo



总结:程序逆向可以先采用 “逆其道而为之”的思想,显示改变eip试探程序是否能如我们所愿,如果如我们所愿就返回分析如何满足条件让其自主执行正确的分支。另外有关delphi程序注意使用E2A按钮事件地址转换器从而在OD中追踪相应的按钮事件

逆向工程初步160个crackme-------6的更多相关文章

  1. 逆向工程初步160个crackme-------2

    有了第一个crackme的经验后,这个crackme用了半个小时就验证成功了.(思路和第一个crackme相似) 动态调试工具:ollydbg (2.10) 文件分析工具:PEID (0.95) 同样 ...

  2. 逆向工程初步160个crackme-------7

    这两天有点发烧,被这个疫情搞得人心惶惶的.我们这里是小镇平常过年的时候人来人往的,今年就显得格外的冷清.这是老天帮让在家学习啊,破解完这个crackme明天就去接着看我的加密解密,算了算没几天就开学了 ...

  3. 逆向工程初步160个crackme-------4

    crackme–3因为涉及到浮点数操作以及一些指令和寄存器(由于本人对浮点指令不了解),所以先隔过去分析后面的程序. 工具:1. 按钮事件地址转换工具E2A 2. PEID 3. Ollydbg 首先 ...

  4. 逆向工程初步160个crackme-------1

    放假在家学习的效率真的很低,看完看雪加密解密的前两章就迫不及待的找了几个crackme练习一下,顺便熟悉ollydbg的使用. 工具:exeinfope(查壳工具),ollydbg(2.10版) 1. ...

  5. 逆向工程初步160个crackme-------3

    这个Crackme3 涉及到浮点指令以及浮点数的存储与运算,我没学习过浮点指令,不得不从网上恶补了1个小时,一边看汇编指令一边百度其指令含义. 回头得好好补补这方面的知识了,太菜了! 我大致了解了一下 ...

  6. [反汇编练习]160个CrackMe之001

    [反汇编练习] 160个CrackMe之001. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  7. [反汇编练习] 160个CrackMe之027

    [反汇编练习] 160个CrackMe之027. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  8. [反汇编练习] 160个CrackMe之026

    [反汇编练习] 160个CrackMe之026. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

  9. [反汇编练习] 160个CrackMe之025

    [反汇编练习] 160个CrackMe之025. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...

随机推荐

  1. python-类的多态的理解

    了解多态 多态指的是一类事物有多种形态 .定义:多态是一中使用对象的方式,更容易编写出通用的代码,做出通用的编程,一适应需求的不断变化 实现步骤: 1.定义父类,并提供公共方法 2.定义子类,并重写父 ...

  2. 剑指 Offer 03. 数组中重复的数字

    剑指 Offer 03. 数组中重复的数字 找出数组中重复的数字. 在一个长度为 n 的数组 nums 里的所有数字都在 0-n-1 的范围内.数组中某些数字是重复的,但不知道有几个数字重复了,也不知 ...

  3. 一键部署etcd集群管理脚本

    一.编写脚本 1 #!/bin/sh 2 # 安装 3 # ./run.sh etcd03 etcd01=http://192.168.2.44:2380,etcd02=http://192.168. ...

  4. 2021精选 Java面试题附答案(一)

    1.什么是Java Java是一门面向对象的高级编程语言,不仅吸收了C++语言的各种优点,比如继承了C++语言面向对象的技术核心.还摒弃了C++里难以理解的多继承.指针等概念,,同时也增加了垃圾回收机 ...

  5. arthas使用

    博客原地址:https://blog.csdn.net/u013076044/article/details/83626202 arthas使用 文章目录 准备 启动Demo 进入arthas控制台 ...

  6. PAT B1033 旧键盘上的几个键又毁坏了,于是在输入一段文字时,对应得的字符就不会出现。

    题中可用的字母包括大小写(给出的坏键的字母,全为大写),数字,"_" "," "." "-" "+" ...

  7. Java【File类、递归】

    File 1.在io包中 操作电脑中的文件和文件夹 java.io.File 类是文件和目录路径名的抽象表示,主要用于文件和目录的创建.查找和删除等操作. 我们可以使用File类的方法     创建一 ...

  8. Python 多线程(一)

    Python多线程(一) 目录 Python多线程(一) 线程 Python线程模型 Python虚拟机按照下面所述方式来切换线程 Threading模块 未引进线程 结果 引入线程 方式一:创建Th ...

  9. 17. Vue2.4+新增属性$listeners

    现在我们来讨论一种情况,A组件与C组件怎么通信,我们有多少种解决方案? 我们使用VueX来进行数据管理,但是如果项目中多个组件共享状态比较少,项目比较小,并且全局状态比较少,那使用VueX来实现该功能 ...

  10. istio之envoy常见术语及状态码

    基本术语 Downstream(下游):下游主机连接到 Envoy,发送请求并接收响应,即发送请求的主机. Upstream(上游):上游主机接收来自 Envoy 的连接和请求,并返回响应,即接受请求 ...