exp编写小技巧

exp编写小技巧

1.代码对齐

exp中填写地址时要注意代码长度的填充

2. 填充为指定长度

3. 链接远程服务器或者链接本地文件

# 远程
r = remote('目的IP或目标URL',目标端口号)
# 本地
r = process('./文件名')

4. 格式转换

32位程序对应p32 / u32,64位对应p64 / u64

>>> p32(0x78739736)
b'6\x97sx'
>>> hex(u32('6\x97sx'))
'0x78739736'

5. 环境变量

context是pwntools用来设置环境的功能。在很多时候,由于二进制文件的情况不同,我们可能需要进行一些环境设置才能够正常运行exp,比如有一些需要进行汇编,但是32的汇编和64的汇编不同,如果不设置context会导致一些问题。

context(os='linux', arch='amd64', log_level='debug')  # 如果不设置默认是32位

这句话的意思是:

  1. os设置系统为linux系统,在完成ctf题目的时候,大多数pwn题目的系统都是linux
  2. arch设置架构为amd64,可以简单的认为设置为64位的模式,对应的32位模式是’i386’
  3. log_level设置日志输出的等级为debug,这句话在调试的时候一般会设置,这样pwntools会将完整的io过程都打印下来,使得调试更加方便,可以避免在完成CTF题目时出现一些和IO相关的错误。

6. 获得汇编指令的机器代码

>>> asm('mov eax, 0')
b'\xb8\x00\x00\x00\x00'

因为asm和架构有关系,因此使用前一定要设定好相关的context架构参数

7. 把权限交给用户

r.interactive()

8. shellcode

pwntools提供简单的shellcode支持,使用shellcraft()可以得到简单的shellcode

它的返回值是汇编指令

>>> print(shellcraft.sh())
    /* execve(path='/bin///sh', argv=['sh'], envp=0) */
    /* push b'/bin///sh\x00' */
    push 0x68
    push 0x732f2f2f
    push 0x6e69622f
    mov ebx, esp
    /* push argument array ['sh\x00'] */
    /* push 'sh\x00\x00' */
    push 0x1010101
    xor dword ptr [esp], 0x1016972
    xor ecx, ecx
    push ecx /* null terminate */
    push 4
    pop ecx
    add ecx, esp
    push ecx /* 'sh\x00' */
    mov ecx, esp
    xor edx, edx
    /* call execve() */
    push SYS_execve /* 0xb */
    pop eax
    int 0x80

使用时,需要先转换为机器码

shellcode = asm(shellcraft.sh())

pwntools提供许多的shellcode,其他的见:https://docs.pwntools.com/en/stable/shellcraft/amd64.html

9. ELF 操作ELF文件的工具

elf = ELF('pwn')
hex(elf.address)
hex(elf.symbols['write']
hex(elf.got['write'])
hex(elf.plt['write'])

##10. 长度测算cyclic

cyclic 需要的长度
cyclic -l 异常的地点(这里异常的地点给定4字节)

11.接收数据

recv(numb = 字节大小,timeout = default) # 接收指定字节数
p.recvn(N)   # 接受 N(数字) 字符
recall()   # 一直接收知道达到文件EOF
recvline(keepends = True)  # 接收一行,keepends为是否保留行尾的\n
p.recvlines(N)  # 接收 N(数字) 行输出
recvuntil(delims,drop = False)  # 一直读到delims的pattern出现为止
recvrepeat(timeout=default)  # 持续接收直到EOF或timeout
p.interactive()   # 直接进行交互,相当于回到shell的模式,一般在取得shell之后使用

12.发送数据

p.send(payload)  # 发送 payload
p.sendline(payload)  # 发送 payload,并进行换行(末尾\n)
p.sendafter(some_string, payload)  # 接收到 some_string 后, 发送你的 payload
p.sendlineafter(some_string, payload)  # 接收到 some_string 后, 发送你的 payload,加个换行

13.填充字符,字符串向右/向左填充

填充时,需要保证填充的字符和原字符是一个类型

>>> type(str)
<class 'str'>
>>> tmp = b'A'
>>> print(tmp.ljust(10, b'B'))
b'ABBBBBBBBB'
>>> tmp2 = "A"
>>> type(tmp2)
<class 'str'>
>>> print(tmp2.ljust(10, 'B'))
ABBBBBBBBB

14.寻找ROP

可以使用ROPgadget工具寻找可用的ROP,使用模板如下:

ROPgadget --binary "param1"  --only 'pop|ret' | grep 'param2' 
# param1: 文件名
# param2: 要搜索的相关寄存器

使用样例如下:

$ ROPgadget --binary "./rop"  --only 'pop|ret' | grep 'eax'
0x0809ddda : pop eax ; pop ebx ; pop esi ; pop edi ; ret
0x080bb196 : pop eax ; ret
0x0807217a : pop eax ; ret 0x80e
0x0804f704 : pop eax ; ret 3
0x0809ddd9 : pop es ; pop eax ; pop ebx ; pop esi ; pop edi ; ret

$ ROPgadget --binary "./rop"  --only 'int'
Gadgets information
==============
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值