esp
与刚开始不一样,还没有平衡堆栈,由上图下面的add esp, 8
用于平衡堆栈 , 这种方式就叫外平栈 。
文章插图
文章插图
要覆盖返回地址,即
ebp + 4
,覆盖了ebp
之后还需要再覆盖ebp + 4
的位置,64位下为ebp + 8
,如上图所示401171
即为返回地址裸函数示例leave
指令相当于这两条指令:movl %ebp, %esp即令esp=ebppopl %ebp 即 ebp = M[esp],esp = esp + 4
int __declspec(naked) plus(){__asm{//在函数调用之前会先push 1 push 2(传参数)call后会执行push 返回地址//保留调用前的栈底push ebp//提升堆栈mov ebp,espsub esp,0x40//保留现场push ebxpush esipush edi//填充缓冲区主要用于存储函数的局部变量mov eax,0xccccccccmov ecx,0x10// 之所以是10 是因为之前提升堆栈0x40 / 4 = 10栈一个格四个字节lea edi,dword ptr ds:[ebp-0x40]rep stosd //每次填充四个字节,重复16次//函数的核心功能ebp + 0x4为返回地址mov eax,dword ptr ds:[ebp+0x8]//把第一个参数给eaxebp+0x4为函数返回地址add eax,dword ptr ds:[ebp+0xc]//第二个参数 + eax -> eax//恢复现场pop edi// 取出栈顶给edi,然后esp+4pop esi// 取出栈顶给esi,然后esp+4pop ebx// 取出栈顶给ebx,然后esp+4//降低堆栈mov esp,ebppop ebp//恢复栈底,刚开始ebp保留过ret//相当于pop eip 把函数返回地址401171给eip然后 rsp + 4}}//裸函数,系统不会生成任何指令,调用时会出错,会导致指令跳转后回不来,往往需要自己写入汇编指令
Pwntools用法参考手册- 连接:本地process()、远程remote( , );对于remote函数可以接url并且指定端口
- 数据处理:主要是对整数进行打包:p32、p64是打包为二进制 , u32、u64是解包为二进制
- 设置目标系统架构及操作系统
>>> context.arch= 'i386'>>> context.os= 'linux'>>> context.endian= 'little'>>> context.word_size = 32
当然 , 你也可以一次性设置好这些变量:
>>> asm('nop')'\x90'>>> context(arch='arm', os='linux', endian='big', word_size=32)>>> asm('nop')'\xe3 \xf0\x00'
- IO模块:这个比较容易跟zio搞混 , 记住zio是read、write , pwn是recv、send
send(data): 发送数据sendline(data) : 发送一行数据,相当于在末尾加\nrecv(numb=4096, timeout=default) : 给出接收字节数,timeout指定超时recvuntil(delims, drop=False) : 接收到delims的pattern(以下可以看作until的特例)recvline(keepends=True) : 接收到\n,keepends指定保留\nrecvall() : 接收到EOFrecvrepeat(timeout=default) : 接收到EOF或timeoutinteractive() : 与shell交互
- ELF模块:获取基地址、获取函数地址(基于符号)、获取函数got地址、获取函数plt地址
e = ELF('/bin/cat')>>> print hex(e.address)# 文件装载的基地址0x400000>>> print hex(e.symbols['write']) # 函数地址0x401680>>> print hex(e.got['write']) # GOT表的地址0x60b070>>> print hex(e.plt['write']) # PLT的地址0x401680>>> print hex(e.search('/bin/sh').next())# 字符串/bin/sh的地址
- 在编写exp时,最常见的工作就是在整数之间转换,而且转换后,它们的表现形式就是一个字节序列,pwntools提供了打包函数 。
p32/p64: 打包一个整数 , 分别打包为32位或64位u32/u64: 解包一个字符串,得到整数# 比如将0xdeadbeef进行32位的打包,将会得到'\xef\xbe\xad\xde'(小端序)payload = p32(0xdeadbeef)#pack 32 bits numberpayload = p64(0xdeadbeef)#pack 64 bits number
- 汇编和反汇编
# 汇编:>>> asm('nop')'\x90'>>> asm('nop', arch='arm')'\x00\xf0 \xe3'# 可以使用context来指定cpu类型以及操作系统>>> context.arch= 'i386'>>> context.os= 'linux'>>> context.endian= 'little'>>> context.word_size = 32# 反汇编>>> print disasm('6a0258cd80ebf9'.decode('hex'))0:6a 02push0x22:58popeax3:cd 80int0x805:eb f9jmp0x0
注意,asm需要binutils中的as工具辅助 , 如果是不同于本机平台的其他平台的汇编,例如在我的x86机器上进行mips的汇编就会出现as工具未找到的情况,这时候需要安装其他平台的cross-binutils 。
- Shellcode生成器
>>> print shellcraft.i386.nop().strip('\n')nop>>> print shellcraft.i386.linux.sh()/* push '/bin///sh\x00' */push 0x68push 0x732f2f2fpush 0x6e69622f...
推荐阅读
- 四十一 增删查改分页 Java开发学习----MyBatisPlus标准数据层开发
- 中 学习ASP.NET Core Blazor编程系列十——路由
- CC1,3,6回顾
- 图学习【参考资料2】-知识补充与node2vec代码注解
- 二十四 设计模式学习:Spring 中使用到的设计模式
- Java安全之CC3
- TensorFlow深度学习!构建神经网络预测股票价格!?
- JUC学习笔记——共享模型之管程
- Seata Server 1.5.2 源码学习
- 2022极端高温!机器学习如何预测森林火灾?? 万物AI