本次实践的对象是一个名为pwn1的linux可执行文件。
该程序正常执行流程是:main调用foo函数,foo函数会简单回显任何用户输入的字符串。
该程序同时包含另外一个代码片断,getShell,会返回一个可用Shell。正常状况下这个代码是不会被运行的。咱们实践的目标就是想办法运行这个代码片断。linux
该实践须要同窗们熟悉Linux基本操做,能看懂经常使用指令,如管道(|),输入、输出重定向(>)等。
理解Bof的原理。
能看得懂汇编、机器指令、EIP、指令地址。
会使用gdb,vi。shell
(1)先把原文件复制本身的文件夹里,进行反汇编
网络
其中call 8048491
是汇编指令,这条指令将调用位于地址8048491
处的foo函数;其对应机器指令为e8 d7ffffff
,EIP的值应该是下条指令的地址,即80484ba。
main函数调用foo,对应机器指令为“ e8 d7ffffff”,调用getShell,只要修改“d7ffffff”为,"getShell-80484ba"对应的补码就行,即c3ffffff。函数
(2)在vi中切换为16进制模式:%!xxd
,查找要修改的内容/e8d7
,找到后先后的内容和反汇编的对比下,确认是地方是正确的,修改d7为c3,转换16进制为原格式:%!xxd -r
,存盘退出vi。
命令行
(3)再反汇编,运行下改后的代码,会获得shell提示符#
3d
(1)复制pwn1
文件为5238pwn1
文件,使用GDB调试
调试
(2)查看寄存器的值
code
(3)再次调试查看是哪一个字符被覆盖到了eip中:
对象
若是输入字符串1111111122222222333333334444444412345678,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码。那只要把这四个字符替换为 getShell 的内存地址,输给pwn1,pwn1就会运行getShell。
(4)低字节放在高位的大端法,即输入11111111222222223333333344444444\x7d\x84\x04\x08
由为咱们无法经过键盘输入\x7d\x84\x04\x08这样的16进制值,因此先生成包括这样字符串的一个文件。\x0a表示回车,若是没有的话,在程序运行时就须要手工按一下回车键。
blog
关于Perl:
Perl是一门解释型语言,不须要预编译,能够在命令行上直接使用。
使用输出重定向“>”将perl生成的字符串存储到文件input中。
(5)用16进制查看指令xxd查看input文件的内容是否如预期,而后将input的输入,经过管道符“|”,做为pwn1的输入。