病毒分析与防护 反汇编工具的使用 修改输出 crackme3.exe注册
反汇编工具的使用
【实验目的】
-
熟悉动态分析工具OllyDBG的界面和常用模块
-
熟悉静态分析工具IDA的界面和常用模块
-
掌握使用OllyDBG分析修改可执行文件的方法
【实验原理】
1OD界面
a. 反汇编窗口:显示被调试程序的反汇编代码,标题栏上的地址、机器码、反汇编代码、注释。
b. 寄存器窗口:显示当前所选线程的 CPU 寄存器内容
c. 信息窗口:显示反汇编窗口中选中的第一个命令的参数及一些跳转目标地址、字串等
d. 数据窗口:显示内存或文件的内容。右键菜单可用于切换显示方式。
e. 堆栈窗口:显示当前线程的堆栈。
2OD使用
(1) 快捷键
a) F2:设置断点
b) F9:运行
c) F8:单步步过
d) F7:单步步入
e) F4:运行到选定位置
f) CTRL + F9:执行到返回
g) CTRL + F2:重新开始
h) ALT + F9:执行到用户代码
(2) 查找可执行文件中所有字符串:
在“反汇编窗口”
单击鼠标右键,选择“查找”
选项可查看可执行文件反汇编代码的“所有参考文本字串”
(3) 修改某个内存地址的数据:
在“数据窗口”按“Ctrl+G”
,可查找某个内存地址的值。
在“数据窗口”
,选中要修改的数据,单击鼠标右键,选择“二进制”
选项 的“编辑”
项,可修改数据值。
在“数据窗口”
,单击鼠标右键,选择“复制到可执行文件”
选项,再选择 “保存文件选项”
- OD的使用
https://www.bilibili.com/video/BV1cE411f7sE?p=1
【实验内容】
参看《课3-实验步骤》
1使用VC 6.0 编写win32 控制台程序
Hello world,得到可执行文件hello.exe
a) 创建新的工程hello:Win32 Console Application
b) 创建CPP源文件
c) 写入代码
#include<iostream> //cout头文件
#include "windows.h" //syeten头文件
using namespace std;
VOID displasy(bool bhello)
{
if (bhello)
cout<<"Hello World!\n";
else
cout<<"Reverse Me!\n";
}
int main(int argc, char* argv[])
{
bool bFlag=true ;
displasy(bFlag);
system("pause"); //系统命令pause,在屏幕输出press any key
return 0;
}
2更改输出
将hello.exe的输出由“Hello World!”改为“Reverse Me!”
- 在反汇编窗口,单击鼠标右键。查找所有
- 在弹出的对话框中
R
框,单击鼠标右键,选择‘查找文本’
。查找“Hello World”
- 在弹出的对话框中,单击鼠标右键,选择‘查找文本’。查找“Hello World”
跳转到对应位置
- 双击进入
- 反汇编窗口,选中’Hello World’所在的行,单击鼠标右键-分析-从模块中删除分析。删除掉 OD的分析结果。
- 反汇编窗口,选中’Hello World’所在的行,单击鼠标右键-分析—分析代码
修改代码
直接修改内容
本方式直接修改字符内容,
- 从反汇编窗口找到字符串Hello World在内存中的地址,复制地址43402C,后点取消
- 在内存窗口,查找地址。CtrL+G弹出查找内存地址的窗口。
- 修改内存中的数据
- 此处需要保证修改前后占用空间大小相同,原末尾的
0A
前移,最后填充00
![]() |
修改前 |
---|---|
修改后 | ![]() |
- 选中修改的数据,右键选择
复制到可执行文件
-
再次右键即可保存
-
效果正确
修改代码逻辑
对于此部分代码,我们可以修改逻辑
00401172 je short 00401188
00401174 push 0043402C ; ASCII "Hello World!",LF
00401179 push offset std::cout
0040117E call 00401096
00401183 add esp, 8
00401186 jmp short 0040119A
00401188 push 0043401C ; ASCII "Reverse Me!",LF
0040118D push offset std::cout
00401192 call 00401096
je
相等跳转,与之相对的是jne
不等跳转
双击修改指令
此处OD自动更改为jnz
指令, if(ZF!=0)则跳转,所以说这两条指令完全没区别
复制到可执行
保存文件
也可以实现
3使用OD找到crackme3.exe的注册码
打开程序直接点击,发现弹窗Beggar off!
内容为Wrong Serial,try again!
。
使用OD打开程序,右键查找,所有文本模式。
再右键查找对应字符串Wrong Serial,try again!
。
并在此处发现大量预留字符串
00440EDC mov ecx, 00440FC8 ;ASCII "No Name entered"
00440EE1 mov edx, 00440FD8 ;ASCII "Enter a Name!"
00440F08 mov ecx, 00440FE8 ;ASCII "No Serial entered"
00440F0D mov edx, 00440FFC ;ASCII "Enter a Serial!"
00440F2F mov edx, 00441014 ;ASCII "Registered User"
00440F4C mov edx, 0044102C ;ASCII "GFX-754-IER-954"
00440F5A mov ecx, 0044103C ;ASCII "CrackMe cracked successfully"
00440F5F mov edx, 0044105C ;ASCII "Congrats! You cracked this CrackMe!"
00440F74 mov ecx, 00441080 ;ASCII "Beggar off!"
00440F79 mov edx, 0044108C ;ASCII "Wrong Serial,try again!"
00440F8E mov ecx, 00441080 ;ASCII "Beggar off!"
00440F93 mov edx, 0044108C ;ASCII "Wrong Serial,try again!"
00440FC8 ascii "No Name entered",0
00440FD8 ascii "Enter a Name!",0
00440FE8 ascii "No Serial entere"
00440FF8 ascii "d",0
00440FFC ascii "Enter a Serial!",0
00441014 ascii "Registered User",0
0044102C ascii "GFX-754-IER-954",0
0044103C ascii "CrackMe cracked "
0044104C ascii "successfully",0
0044105C ascii "Congrats! You cr"
0044106C ascii "acked this Crack"
0044107C ascii "Me!",0
00441080 ascii "Beggar off!",0
0044108C ascii "Wrong Serial,try"
0044109C ascii " again!",0
004410A9 mov ecx, 004410C8 ;ASCII "Have a nice day"
004410AE mov edx, 004410D8 ;ASCII "Mail Name/Serial to acidbytes@gmx.net !"
004410C8 ascii "Have a nice day",0
004410D8 ascii "Mail Name/Serial"
004410E8 ascii " to acidbytes@gm"
004410F8 ascii "x.net !",0
00441270 push ebp ;(初始 CPU 选择)
00441276 mov eax, 00441160 ;UNICODE "!"
00441293 mov edx, 004412D0 ;ASCII "Crackers For Freedom CrackMe v3.0"
004412D0 ascii "Crackers For Fre"
004412E0 ascii "edom CrackMe v3."
004412F0 ascii "0",0
这里我们选择"CrackMe cracked successfully"
处,双击进入查看汇编代码。
发现使用了众多jnz
即不等跳转。以及call
调用了众多函数。其很有可能是通过函数进行判断。
动态调试
向上拉去,到合适的地方打下断点F2,运行至此F9,在弹出的额程序中我们随意(随着梁意)输入,并点击Resgister now
随后F8逐步执行。
在这一步我们发现用户名已经被放入内存
00440ECF call 00420E20
0019F854 0223F008 ASCII "SKPrimin"
在下一步发现直接跳转。
CMP结果 | ZF |
---|---|
目的操作数 < 源操作数 | 0 |
目的操作数 > 源操作数 | 0 |
目的操作数 = 源操作数 | 1 |
jnz
结果不为零(或不相等)则转移,根据ZF
标志位进行判断。
两句结合效果是进行用户名非空判断,输入非空则会进行下一步判断
00440ED4 cmp dword ptr [ebp-4], 0
00440ED8 jnz short 00440EF2
继续F8单步步过,发现接收了序列号,两次接收输入都调用了00420E20
函数
同样是进行序列号是否为空的判断。
接下来为了以探究究竟,我们在下一个00420E20
函数F7单步步入,发现是个三参数入栈的操作。推测可能是scanf函数
随后F8直到返回主程序,发现在调用了00403B2C
函数之后便大幅度跳转,直到push 0
。
在运行就直接结束咧。
至此我们可以肯定00403B2C
函数暗藏玄机,Ctrl + F2重新开始。
探究具体函数
熟练地找到字符串,双击进入,熟练地打断点、F9运行至此,同样是随机输入,点击Resgister now,F7单步步入。
但这一次我们选中到00403B2C
,F4运行到选定的位置,F7步入。
进入后发现是个复杂的程序
je
指令是是在(ZF=0)时进行跳转,也就是相等的时候跳转。
则刚进来就执行的这段代码,是比较eax,edx是否相等
00403B33 39D0 cmp eax, edx
00403B35 0F84 8F000000 je 00403BCA
而敲好在其执行前,eax和eax刚刚被赋值,故其相当于比较输入的值与00441014 内存位置的值
00440F2C mov eax, dword ptr [ebp-4]
00440F2F mov eax, 00441014 ; ASCII "Registered User"
而此处正是字符串"Registered User"
00441014 ascii "Registered User",0
至此我们得知,输入的用户名必须是"Registered User"。
同样的方式重新出发。
这一次直奔序列号部分,发现调用同一个函数
而这次我们可以看出,正是在此,由于比对结果不正确,变跳过了"Congrats! You cracked this CrackMe!"
部分。
而0044102C
的内容为"GFX-754-IER-954"
。
接下来,我们单独打开程序。输入Registered User
和GFX-754-IER-954
。可以看到,成功注册!
【小结或讨论】
-
本次实验是对反汇编工具的一次综合使用,先是使用OD静态修改了字符串参数,或是一条指令。熟悉了OD的基本操作以及快捷键。
-
随后动态调式开始找寻注册码,有了上一次的经验,这次我们直接一字符串为切入点,很快找到了相关的代码段,进过一些处理便开始动态调试。
-
动态调试的过程中单步步入、单步步过、运行到此等一些功能灵活搭配,步入一些关键函数查找代码之间的逻辑关系。步过一些不关紧要的函数,加快进程。
-
本次也是对汇编语言的一次运用,JE、JNZ的关系和含义等等,一些跳转指令也是破译代码含义的关键。