接收远端传来的数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

interactive() : 在取得shell之后使用,直接进行交互,相当于回到shell的模式。

recv(numb=字节大小, timeout=default) : 接收指定字节数。

recvall() : 一直接收直到达到文件EOF。

recvline(keepends=True) : 接收一行,keepends为是否保留行尾的\n。

recvuntil(delims, drop=False) : 一直读到delims的pattern出现为止。

recvrepeat(timeout=default) : 持续接收直到EOF或timeout

payload = flat([变量1,变量2,变量n]) 将多个变量转换为二进制字符串

接收远端传来的数据

1
2
3
4
5
6
7
8
9

send(data) : 发送数据。

sendline(data) : 发送一行数据,相当于在数据末尾加\n。

sendlineafter("字符串",data) : 在这一串字符串结束之后发送数据

send 和 sendline 的区别是: sendline 多发送了一次回车

环境设置以及脚本调试

1
2
3
4
5
6
7

context(arch='amd64', os='linux', log_level='debug') 32位就用 arch= 'x86'/'i386'

gdb.attach(io)
pause()
可以进行对我们的脚本进行调试,并发现一些其他的信息

ljust()方法

描述

Python ljust() 方法返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。

语法

ljust()方法语法:

1
str.ljust(width[, fillchar])

参数

1
2
3
4

width -- 指定字符串长度。

fillchar -- 填充字符,默认为空格。

返回值

返回一个原字符串左对齐,并使用空格填充至指定长度的新字符串。如果指定的长度小于原字符串的长度则返回原字符串。

实例

以下实例展示了ljust()的使用方法:

1
2
3
4
5
6
#!/usr/bin/python

str = "this is string example....wow!!!";

print str.ljust(50, '0');

以上实例输出结果如下:

1
this is string example....wow!!!000000000000000000

elf.symbols[]

elf.symbols[]pwntoolsELF 类的核心属性,也是 PWN 做题的地址速查手册

简单说:加载 ELF 文件后,它是一个字典 → 键 = 符号名(函数 / 全局变量名),值 = 该符号在程序中的虚拟内存地址(无 PIE)/ 偏移(有 PIE)

符号类型 返回值(无 PIE) 返回值(开 PIE) 实战用途
程序自身函数(win/main) 函数绝对虚拟地址 函数文件偏移 直接劫持 EIP/RIP 跳转到后门
全局 / 静态变量(buf/flag) 变量绝对虚拟地址 变量文件偏移 读写 / 覆盖全局变量
动态函数(libc:printf/read) 函数GOT 表地址 函数GOT 表偏移 泄露 libc 基址、构造 ROP

简写:elf.sym[xxx] = elf.symbols[xxx]

1
2
3
4
5
6
7
8
9
10
11

# 1. 动态函数的GOT地址(sym=got,完全等价)
printf_got = elf.sym['printf'] # ✅ 最常用
printf_got = elf.got['printf'] # 同上

# 2. 动态函数的PLT表地址(调用动态函数的跳板)
printf_plt = elf.plt['printf']

# 3. 程序自身函数/全局变量(只有sym能拿)
win_addr = elf.sym['win']
buf_addr = elf.sym['buf']

避坑指南

  1. Stripped 程序(去符号)

    编译时加-s的程序,elf.sym[]只有动态函数符号(read/printf),自身函数(main/win)查不到 → 只能去 IDA 手动找偏移。

  2. 符号名严格匹配

    不是scanf,而是__isoc99_scanf;不是gets,而是_gets → 用print(elf.symbols)打印所有符号核对。

  3. 栈上变量拿不到

    elf.sym[]只能查全局 / 静态变量,栈上局部变量(如函数内的 buf)查不到 → 只能算栈偏移。

  4. 32/64 位无差异

    语法完全一致,只是地址长度用p32()/p64()区分

本质:

elf.symbols[] 本质是 pwntools 帮你解析了 ELF 的符号表

  • .dynsym:动态符号表(存 libc 函数、导出函数)
  • .symtab:静态符号表(存所有函数 / 变量,stripped 后会被删除)