20165207 Exp1 PC平台逆向破解

20165207 Exp1 PC平台逆向破解

0.写在最前面

在做三个实验的前两个的时候,我还没有到博客里去看作业的要求。当时我的主机名是kali5207也就是用我的学号命名的,要求的是姓名全拼命名kali,所以当时我的命名是不规范的。故将改名这一段写在最前面。修改主机的名字也就是修改“hostname”,实际上需要修改的是一个配置文件,在/etc目录下文件名就是hostname。
如图:

进入vim编辑器之后,只有一条内容,就是当前的名字“kali5207”,将其修改为:LiTianLin20165207Kali,然后命令模式下wq保存退出,再重启虚拟机。
重启之后效果如下
如图:

PS:本来我想用下划线规则来改名,就是:litianlin_20165207_kali,但是重启之后两条下划线就没有了。因为下划线不被识别显示,所以改用了驼峰规则。

1.1需要回答的问题

1.1.1实验收获与感想

上学期有一门课的教材是《深入理解计算机系统》,里面有讲x86-64汇编。所以上课讲的时候,我觉得我听得很懂。自己做起来的话,就又是另一回事了。收获就是,函数栈帧掌握的更好了,了解了gdb的强大的另一面。

1.1.2什么是漏洞,漏洞有什么危害

我理解漏洞就是程序在逻辑结构上的不严谨的地方,并且可以被攻击者利用。
漏洞的危害比如,蠕虫病毒可以用漏洞来进行传播、攻击者可以利用漏洞对被攻击者进行远程控制或者窃取被攻击者信息、浏览器漏洞给网页木马提供机会等等。

1.2 需要描述的内容

1.2.1相应指令的机器码

NOP:0x90
JNE:0x75
JE:0x74
JMP:0xEB(8位相对短跳转时)
0xE9(16位相对跳转时)
0xFF(16位/32位绝对跳转时)
EA(远距离绝对跳转并且地址由操作数ptr(指针)给出 格式为:ptr16:32)
CMP:0x38(目的操作数为8位内存或寄存器,源只能为8位寄存器)
0x39(目的是16位内存单元或者寄存器,源只能为16位寄存器)
0x3A(目的是8位寄存器,源是8位内存单元或者寄存器)
0x3B(目的是8位寄存器,源是8位内存单元或者寄存器)
0x3C(源操作数是8位立即数,目的是AL)
0x3D(源操作数是16位立即数,目的是AX)


下面的关于反汇编与16进制编程器、能正确修改机器指令改变程序流程、能正确构造payload进行bof攻击的三个要求在下面的实验过程中有所体现。

2.实验内容

2.1修改机器码,改变程序执行流

首先把老师提供给我们的可执行文件pwn1拷贝到虚拟机里,然后复制一份,用这份来做这个第一个实验。

提前已经知道了pwn1这个文件有关键的三个函数除了main函数之外还有foo函数和getshell函数。这第一个小实验就是要把main函数中调用foo函数的call指令进行修改,最终让call指令调用getshell函数。
既然如此,首先要反汇编一下这个文件,了解其具体内容。使用命令objdump用-d参数使用其反汇编功能,在利用管道符将结果传递给more让more来进行分页查看

好了,在这里最上面有getShell的起始地址804847d

还有下面call调用foo的汇编指令以及对应的机器码,汇编指令是:call 8048491 译码之后变成了e8 d7 ff ff ff ,其中e8代表了call,而后面的d7 ff ff ff是一个“偏移”,用它加上ip寄存器的值(call的下一条是80484ba)在存进ip里便能实现函数调用,也就是说:eip + d7 ff ff ff = 8048491,所以说我们要改的是32位的d7 ff ff ff让改之后的东西加上ip之后变成804847d
于是,打开功能强大的宿主机win10的计算器,注意选DWORD(双字,即32比特),然后计算一下80484ba离804847d有多远

算出来之后的值,求补码之后得到了c3 ff ff ff。所以只要把对应位置的d7改成c3就可以了
vim打开这个文件,在命令模式下输入%!xxd以16进制的方式查看,再输一个斜杠"/"进行搜索,直接搜索e8d7没有搜到

因为e8和d7分开了,直接搜d7,再确认一下就好了

换成c3,我是用i进入插入模式换的
换好之后要给人家恢复原貌不能直接wq保存退出,要先xxd -r撤销掉这个16进制的效果。然后执行这个pwn5207_1,获得root权限

2.2利用缓冲区溢出攻击覆盖掉返回地址,然后执行getshell

刚才我们已经看过了foo函数,有一个很关键的一句话给了我们缓冲区大小的信息:

常被用来做返回值的eax指向了ebp向上28个字节的地方算上ebp里面存的32位的地址,那要被覆盖的无用的地方应该是32个字节。
用gdb验证一下:


所以说,报错内容里面说找不到的地址“34333231”就是我在32个字节之后输进去的1234的ascii码,栈底就是那1234之前的四个4的ascii码
那么我需要做的就是,在32个字节之后放进去我需要让程序跳到的那个位置(804847d),下面是我在上这周二的课之前的一个想法:
大概就是,输入四个字符四个字符被用ascii码翻译出来之后,那个32位的码就是804847d

问题也很明显,不是每个数都有ascii码,7d和08 还有04都还好说但是遇到了84就没有这个对应的字符了
下面是按照这周二讲的用perl语言的方法做出来的结果:

2.3构造payload进行攻击

这次要输入的东西比上一个小实验更长,结构是:32字节(道理是一样的) + shellcode地址(因为要调注进去的shellcode肯定要先把返回地址变成第一句shellcode的地址) + 爬行区(一堆nop:0x90) + shellcode
所以,这一步最关键的就是找到shellcode的地址,来让payload生效。
操作过程是这样的,我参考老师提供的指导把东西复制了下来,然后覆盖返回地址那里改成1234用以标记

用第二个小实验的管道符的方法运行pwn5207_3,需要注意的是那个用来生成input_shellcode的串是没有回车的(也就是说不手敲回车暂时没有输出),否则敲了下回车执行结束了,gdb根本抓不到这个进程,更不用说通过调试来确定返回地址了。就这样,先不敲回车,让它先阻塞。然后新打开一个标签页,在那里查看pwn5207_3的进程号,在通过进程号调这个进程,在foo返回的位置设置断点。

如图,pwn5207_3的进程号是33209,打开gdb使用attach命令调试33209进程。需要设置断点的最关键的地方就是foo返回的那一句,这一句再往下四个字节之后就要开始shellcode了(那就是shellcode的起始地址,就是刚才那四个字节里要填的东西),以及我们已经知道那一句的地址是80484ae,所以b *0x80484ae设置断点,然后回到开始那个标签,回车,让阻塞的进程往下跑。
于是gdb的标签这边断点命中,此时攻击尚未发生,但是foo函数的栈帧基本到底了,这时候的esp再往下指四个字节(就是跳过返回地址那四个字节)就能指到shellcode开始的地方,所以要看esp的值:

是d2ec,所以shellcode要替换的东西就是ffffd2ec+4=ffffd2f0
改!

成功辽

PS:部分计算过程:

猜你喜欢

转载自www.cnblogs.com/ltl0501/p/10543094.html