简介
实验的思路来自《0day安全:软件漏洞技术分析》第一章。这次实验的内容为如何破解一个简单的密码验证功能的exe文件。经过这次实验能够大致了解软件破解的一些步骤,为二进制漏洞的学习打下基础认知。html
环境和工具
1.系统环境:windows 10
2.工具:IDA、OllyDBG、LordPE、uedit64
工具和实验源码下载:
连接:https://pan.baidu.com/s/1qh91yRkWP4oWW7QBe-2QGQ
提取码:rgo7
windows
知识铺垫
想了一下,仍是以为把相关的知识点嵌入在实验环节里比较好,单独写在这翻来翻去也是比较麻烦的。安全
实验
1.首先编写一个简单的密码验证的可执行文件。语言为C++(其余语言也能够,只要能生成exe)。markdown
#include <stdio.h> #include <string.h> #define PASSWORD "123456" int verify_password(char *p){ int flag; flag = strcmp(p,PASSWORD); return flag; } int main(){ char password[10]; while(1){ printf("input your password:\n"); scanf("%s",password); if (verify_password(password)==0){ printf("TRUE\n"); }else{ printf("FALSE\n"); } } return 0; }
以后生成pwn.exe文件,点击运行测试。函数
当输入123456时返回TRUE表示密码正确,其余字符返回FALSE
工具
2.使用IDA对exe文件进行反编译。File->open->选择exe。以后点击肯定,结果以下图,会看到一串汇编代码。学习
在左侧一栏里找到_main函数。(由于在本例中,判断密码是否正确的条件在main函数中,因此要先找_main,若是判断语句写在了verify_password方法中,则先找_verify_password,_verify_password就在_main上面)点击空格键,能够跳转到相似流程图的模式。
测试
即便不懂汇编语言也不影响理解,能够看到在jnz short loc_4014CD
下面有两个分支,分别对应着判断为true和false的操做。而jnz
的意思为jump if not zero,非零跳转,与其相反的是jz
:jumb if zero,零即跳转。而是0仍是1是由前面的test eax, eax
来计算得出的,后面会讨论这个问题。spa
3.咱们使用IDA的目的一是要找到判断语句的跳转代码,二是要找到这个判断语句所在的虚拟内存地址(VA)。按空格返回汇编代码模式,能够看到jnz short loc_4014CD
的虚拟内存为0x004014BD(以下图)。
要注意的是,这个地址是虚拟内存内的地址,若是只是在内存里将jnz short loc_4014CD
改成jz short loc_4014CD
,则仅仅是运行的进程被更改,存在硬盘的程序是没有发生变化的。(操做系统知识点:当一个程序运行时,会建立一个进程,并将自身的代码放进程内而后在内存中运行。)
操作系统
4.接下来就分别演示经过修改内存和修改硬盘内程序两种方式达到实验目的。(若是仅仅是想到的密码的话,直接查看exe内的字符串就能看到123456,但这不是咱们学习的目的。)
先来尝试内存破解。要使用到OllyDBG工具。打开,file->open->pwn.exe文件。此时也打开了pwn.exe文件控制台,不要关闭,关闭则pwn.exe进程结束。
按ctrl+G键,输入以前咱们获得的jnz short loc_4014CD
的VA地址,即0x004014BD。
按F2添加断点,以后按F9运行,在控制台输入错误的密码,回车。此时在右上角一栏能够看到以下(前提是你的环境和代码跟本例是同样的,即便不同其实思路也是同样):
回到咱们以前提到的test eax, eax
,eax就是一个寄存器,此时它存的值为00000001,test的意思就是逻辑与操做,并将结果存在ZF(零标志位)中,即00000001&00000001=1,运算结果为1,非零,那么ZF=0,然后面的jnz
是结果不为0则跳转,由于ZF=0表示运算结果不为0,因此跳转。好吧,我认可写这篇文章整理思路的时候绕进去了╭(╯^╰)╮,若是只是为了好理解能够理解成test
运算后结果不为0,因此jnz
跳转,这样也是能够,但总有种歪打正着的感受。(你可能想到了第二层,可是我却已经第五层了,就是这种感受。)
补充:若是你一步一步执行,会发现 EAX寄存器的值一开始是咱们输入的‘asd’这个错误密码,后来在_strcmp方法中被置为了00000001。_strcmp就是代码里的 strcmp()方法。
如今咱们已经知道接下来要发生的事情了,jnz
跳转到FALSE的语句上。其实在OllyDBG已经有相关的提示了。如图左下角Jump is taken,下面是跳转的地址,为pwn进程的0x004014CD的VA地址。
此时咱们继续按F9放行,查看控制台。控制台返回了FALSE,咱们的目的是要返回TRUE。
首先。将jnz
改为jz
,会发现系统将jz
改为了je
,可是不影响,由于两个方法功能上是同样的。以下图,要注意前面的74 0E是对应的16进制机器语言。改完以后,在控制台输入和以前同样的密码即asd,再次按F9放行程序。
结果显示这次为TRUE。
5.上面那个是内存修改的方式,此次是直接修改exe文件内的机器语言来实现咱们的目的。在这以前,咱们须要计算jnz
这个操做命令在exe的位置。以前咱们已经获得了运行时它的进程在内存的虚拟地址,即0x004014CD。下面要补充一些知识点,对PE文件格式在硬盘和内存比较熟悉的同窗能够直接跳过。
以下图,windows 10操做系统下,内存块是以0x00001000为单位分割的,而硬盘是以0x00000400为单位进行分割的。并且代码是存放在exe文件中.text段内,也就是说咱们所须要的 jnz
就存放在.text中。如今已知 jnz
在虚拟内存的地址为0x004014CD,而exe文件的虚拟地址基址均为0x00400000,若是要计算出在硬盘的格式,应为0x004014CD-0x00400000-虚拟内存地址文件头大小 +硬盘地址文件头大小
如今咱们须要虚拟内存地址文件头的大小和硬盘地址文件头的大小,咱们能够用LordPE工具来查看。PE Editor -> Sections。如图能够看到咱们所须要的两个数据。第一个是虚拟内存的,第二个是硬盘的。
因而就能够计算出硬盘内的jnz
地址。
0x004014CD-0x00400000-0x00001000+0x00000400=0x000008BD
得出地址为0x000008BD,接下来使用uedit64工具进行16进制编辑,按Ctrl+G,输入刚刚算出的地址。
根据以前的测试,咱们知道jnz short loc_4014CD
的16进制机器语言对应的是75 0E,再看看上图,说明咱们的计算没有错误,将75改成74(74就是jz
),保存。
测试一下,成功。
总结
1.了解了IDA、OllyDBG、LordPE、uedit64工具的简单实用
2.初步认识了软解破解技术的思路。
3.掌握了PE文件格式在内存和硬盘的计算方法。