您的位置:首页 > 其它

初识二进制与软件破解

2020-04-05 18:29 1351 查看

文章目录

  • 简介
  • 环境和工具
  • 知识铺垫
  • 实验
  • 总结

简介

实验的思路来自《0day安全:软件漏洞技术分析》第一章。此次实验的内容为如何破解一个简单的密码验证功能的exe文件。通过此次实验可以大体了解软件破解的一些步骤,为二进制漏洞的学习打下基础认知。

环境和工具

1.系统环境:windows 10
2.工具:IDA、OllyDBG、LordPE、uedit64
工具和实验源码下载:
链接:https://pan.baidu.com/s/1qh91yRkWP4oWW7QBe-2QGQ
提取码:rgo7



知识铺垫

想了一下,还是觉得把相关的知识点嵌入在实验环节里比较好,单独写在这翻来翻去也是比较麻烦的。

实验

1.首先编写一个简单的密码验证的可执行文件。语言为C++(其他语言也可以,只要能生成exe)。

#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下面有两个分支,分别对应着判断为truefalse的操作。而jnz的意思为jump if not zero,非零跳转,与其相反的是jz:jumb if zero,零即跳转。而是0还是1是由前面的test eax, eax来计算得出的,后面会讨论这个问题。

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文件格式在内存和硬盘的计算方法。

  • 点赞 3
  • 收藏
  • 分享
  • 文章举报
d3f4ult 发布了11 篇原创文章 · 获赞 20 · 访问量 1万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  watermark shadow