• Welcome to the world's largest Chinese hacker forum

    Welcome to the world's largest Chinese hacker forum, our forum registration is open! You can now register for technical communication with us, this is a free and open to the world of the BBS, we founded the purpose for the study of network security, please don't release business of black/grey, or on the BBS posts, to seek help hacker if violations, we will permanently frozen your IP and account, thank you for your cooperation. Hacker attack and defense cracking or network Security

    business please click here: Creation Security  From CNHACKTEAM

Recommended Posts

如果需要对这个实验需要的环境和工具留下评论,我就不一一介绍了,估计也没几个人会看。主要是太多了,不想打字。

要学习这个漏洞,就得学习漏洞的理论知识。

在汇编程序执行过程中,如果需要调用一个函数,通常是调用函数的地址。call指令执行时,会将函数的返回地址(函数执行后下一条要执行的指令的地址)进行堆栈,然后堆栈中的扩展方向是从高地址到低地址。这里可能不是很好理解。我来画个图hhhh。比如我执行call指令,堆栈返回地址的序号是10000,然后需要对我调用的函数的变量进行挤压。我申请了一个空间为10的数组,所以我会申请10个9990到10000的方块来放参数,然后在存储参数的过程中,堆栈指针实际上是从低位地址移动到高位地址的。第一个参数存放在9990,第二个参数存放在9991,但是如果我们的应用空间是10但是实际上有20个参数,那么参数会继续存放在堆栈中,会覆盖原函数返回地址的数据。

4zqf0bhjb0y3243.png

当memcpy函数被执行时,即堆栈被平衡,堆栈中的所有调用都会被推出堆栈,直到返回地址的位置被推出堆栈到EBP,其中EBP的地址是当前指令的地址,EIP的地址是下一条指令的地址。

大家想一想,如果把恶意代码作为参数传入堆栈,然后想办法让函数返回再跳回堆栈执行堆栈中的恶意代码,岂不是有可能实现堆栈溢出?

所以问题是:1。如果我们存储的数据导致了堆栈溢出,那么数据溢出(覆盖返回地址的数据)是从哪里开始的呢?2.如何让返回的主程序EIP返回堆栈执行我们保存的恶意代码?

让我们展示包含溢出漏洞的实验代码程序:

it5422wqkya3244.png

可以看到我们在main函数中调用了溢出函数,并传入了参数shellcode。在溢出函数中,我们调用了memcpy函数,它将字符串复制到数组中。应用的数组长度为10,但我们传递的参数shellcode大于数组的空间。

实验思路:首先找出程序运行时shellcode的哪一部分覆盖了memcpy函数在栈中的返回地址,然后将shellcode中覆盖返回地址的部分修改为jmp esp(回栈)的字节码(编译后的字节码),在shellcode中修改为jmp esp之后我们要执行的恶意代码的字节码,实现溢出。可能这里比较抽象,但是通过调试跟踪你就明白了。我们来记录下调试过程。

用vc 6.0调试,因为可以看到栈的变化过程,也可以看到反汇编的代码,和字节码。以前觉得好难,现在觉得好强大hhhhh。

做一个断点,让鼠标停在断点的代码行上,点一下小手,然后出现一个红点,就是断点:

vmjvisrxpi43245.png

然后点击该框,就可以调试并在断点处停止。如果没有编译,编译器会提醒你编译。去做吧。

zpb1yw2hk0y3246.png

停在断点处后,点击我圈出来的三个图标,从左到右,分别显示寄存器、内存状态(稍后可以搜索堆栈的内容)、反汇编代码。

qhgxdhc1iol3247.png

然后点击下一步,圈出来的就是踩踩踩。我一般喜欢踩,但如果不懂可以去百度。

ucmuqlvutzc3248.png

可以看到调用memcpy并将返回地址堆栈到ebp,然后ret,返回执行。

ing="lazy" src="https://www.icode9.com/i/l/?n=22&i=blog/2806024/202205/2806024-20220501150159735-260039688.png"/>

 

当执行到pop ebp前一句时,栈的内容,此时是把esp的地址的内容出栈到ebp中,此时看到内容为46474849,机器读是49484746(这里涉及大端小端存储,不作解释,自行百度)。

cy4c0no4hgi3249.png

 

 然后再往下执行的时候,就会报错,因为把46474849出栈到ebp中,机器下一条就会去找这个地址去执行下一条代码,可是这个地址是没有代码的就会报错。

4g3huw0hjc03250.png

 

 所以,前面思路的第一个问题我们已经解决了,shellcode的内容从46开始就会覆盖返回地址,现在我们解决第二个问题,使下一条指令的地址回到栈中。这个时候我们可以利用动态链接库中的jmp esp,我们这个时候用一个工具去找。就双击Findjmpesp.exe,显示的全都是,我们选第一个。

cst5kx2noue3251.png

 

 然后把这个地址写到shellcode中46474849的位置,然后代替它入栈,细心的同学就发现刚刚出栈的时候怎么是49484746,所以我们写地址到shellcode中的时候也要倒着写,就是da24e477.

irmaycxaaj43252.png

 再重新编译调试一次,是不是出栈以后执行的指令就变成了,jmp esp。

yk5ib3ffgf33253.png

 

 再下一步看看回到栈中以后,执行啥代码。虽然后面机器解释为push,pop啥的,但是它那个字节码其实是我们存到栈里面的,49以后的数字50,51.....

 

 0l541cvbz2n3254.png

 

 所以第三步就是我们把我们要执行的恶意代码的字节码写进来,就会继续执行我们要的操作。如何搞出字节码呢,就是编译器的工作了,我们先把恶意代码的C语言程序写出来,这里我用的是老师给的。

展示一下我的程序,这个程序是汇编代码,它内容是调用一个弹窗函数,然后再调用一个退出程序的函数,这个程序并不是我写的,我们查找并填入两个函数的绝对内存地址:

unrxjd1wldc3255.png

 

 如何找到函数的绝对内存地址:

MessageBox A在user32.dll中的相对地址为3D8DE,user32.dll的基址为77e10000,程序运行的时候,函数的地址就是base+相对地址。所以我们把这两个数加起来77e4d8de。

00lsxhrmvaxcb3256.png

 

 另一个函数,自己算哈:

g2p4uzs3qfq3257.png

 

 然后我们编译运行一下createshellcode.程序看看是什么样的。

y5ut4jjftlw3258.png

 

 然后我们把这个函数asm的部分(弹窗并退出程序)的字节码写到overflow.c函数的shellcode的jmp esp的后面。反汇编可以查看字节码。要把asm部分所有的字节码都抄过去,我知道这个工作量很大,或许网上有脚本hhhh,但是我是手抄

o4lk0q3ja1t3259.png

 

 然后回到overflow.c,然后我们编译执行一下。

0aphwp3bovs3260.png

 

执行的结果是这样子的,也许细心的同学会发现我的两个弹窗的字不是一样的,因为前面的弹窗的字被我改过的,这个弹窗的字符我用的是原本的字节码。成功实现了栈溢出~~~

 tdf03msrdqi3261.png

 

 本次实验学习介绍就到这里啦!

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now