一、实验内容
本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另一个代码片段,getShell,会返回一个可用Shell。正常情况下这个代码是不会被运行的。我们实践的目标就是想办法运行这个代码片段。我们将学习两种方法运行这个代码片段,然后学习如何注入运行任何Shellcode。
三个实践内容如下:
手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
注入一个自己制作的shellcode并运行这段shellcode。
二、实验过程
方案一:手工修改
(1)首先通过objdump反汇编查看pwn文件中函数的地址
0x0804847d
0x08048491
(2)查看main函数中调用foo函数的代码
80484b5: e8 d7 ff ff ff ;;call 8048491
80484ba: b8 00 00 00 00 ;;mov $0x0,%eax
补码表示,这时候EIP执行的指令为80484ba,call指令就是把这个四个字节放到EIP指令上
(3)根据地址信息计算新的调用地址
main函数调用foo函数分析:
执行到call 8048491 行时发生了调用,此时指令寄存器EIP中存放的信息为0x080484ba。因此有如下计算公式
foo地址 - [EIP] = call指令后的数据
0x08048491 - 0x080484ba = 0x-29
0x-29的补码是d7 ff ff ff,以小端序显示
如果要修改为调用getShell函数,则有如下计算公式:
getShell地址 - [EIP] = call指令后的数据
0x0804847d - 0x080484ba = 0x-3d
0x-3d的补码是ff ff ff c3,小端序为c3 ff ff ff
经过计算,此时相差FFC3
经过刘老师的汇编教程学习后,可知上图显示出本用户可读可写可执行,其他用户无法进行可写可执行操作
此时我们下一步的操作为把d7改成c3
此时我们键入R(更改)分别补上C 3
完成修改任务
显示成功,我们进行下一步任务
方案二:构造字符串
这是我误触后弹出的界面,发现此时返回地址被55555填满
由图片可以看出从输入的第29位开始,1111的ASCII 34343434被写入ESP,2222的ASCII 35353535被写入EIP,即输入的第33到36位为覆盖的返回地址
此时我们键入 XXd input 检查我们的输入是否正确
下面我们进行第三个操作
方案三:注入shellcode
依旧开始调试,确定出返回地址的准确位置
可以看到此时01 02 03 04已经就位
此时我进行多次更改,都无法完成实验操作
此时出现了问题,发现怎样更改但都无法成功运行
于是我重新开始调试,发现了问题
成功完成任务!
三、遇到的问题及解决方法
在操作中遇到的问题
- 问题1:在执行任务2中出现执行错误的情况,显示broken
- 解决方法:由于汇编任务是小端优先,我按照正常顺序输入,出现问题。
- 问题2:在进行shellcode注入时发现每次栈中的地址都是随机的,让我无法准确定位到要注入的位置
- 解决方法:其实这是我没有好好做预习的问题,在这次的指导书中提到,这次实验的顺利进行取决于对地址随机化的关闭,在下面这张图中就是在实验后操作没有关闭地址随机化导致的,对于理论学习的把握一定要认真!
四、实验感想
通过本次实验学习了缓冲区溢出攻击的相关知识和实践操作。之前在信息安全的课程里也学习过,不过也没有很好的掌握,尤其是对EIP和EDP这两个寄存器的认识,本次实验从另一个角度再次学习了这个知识,我对这个缓冲区溢出攻击的理解更进一步,并且通过实际动手实现shellcode注入攻击,让之前所学习的知识变得更具体,更完善,和之前学习的内容相比,我对系统寄存器的功能和汇编语言的相关知识了解更多。这次刘老师和强哥准备的特别充分,让我们这次实验实现的过程特别顺利,但是仍然还有一些细节的知识(比如说一些地址位置的确定,和老师的一部分注释)理解的不是很好,这就让我感受到我还需要继续学习缓冲区溢出的相关知识,来将这些“敌人”们变成我网络渗透学习的新朋友。