(好难,被薄纱了QAQ)

RE

test your Debugger

直接动态调试在提示的位置打断点

得结果

CompileMe!!!

文件打开以后是sln源代码文件??甚至不用逆向?
打开之后:完型填空?

看起来是一个简单的XTEA,但是vs一开就崩溃,vscode也不知道为什么不能运行。。。那先看看题(补全后):

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
namespace NSSCTF
{
internal class Program
{
static void Main(string[] args)
{
var key = new ulong[] { 0x57656c636f6d6520, 0x746f204e53534354, 0x4620526f756e6423, 0x3136204261736963 };
var c = new ulong[] { 0xc60b34b2bff9d34a, 0xf50af3aa8fd96c6b, 0x680ed11f0c05c4f1, 0x6e83b0a4aaf7c1a3, 0xd69b3d568695c3c5, 0xa88f4ff50a351da2, 0x5cfa195968e1bb5b, 0xc4168018d92196d9 };
const ulong e = 0x9E3779B9;
var delta = Enumerable.Range(0, 32).Select(index => e * (32 - (uint)index)).ToArray();

var decryptedBlocks = c.Select((block, index) => new { Value = block, Index = index })
.GroupBy(item => item.I ndex / 2)
.Select(group =>
{
ulong b1 = group.ElementAt(0).Value;
ulong b2 = group.ElementAt(1).Value;
ulong sum = e * 32;

delta.ToList().ForEach(currentDelta =>
{
b2 -= (((b1 << 4) ^ (b1 >> 5)) + b1) ^ (sum + key[(sum >> 11) & 3]);
sum -= e;
b1 -= (((b2 << 4) ^ (b2 >> 5)) + b2) ^ (sum + key[sum & 3]);
});
return new[] { b1, b2 };
})
.SelectMany(block => block)
.ToArray();

ulong[] decryptedText = new ulong[decryptedBlocks.Length];
Array.Copy(decryptedBlocks, decryptedText, decryptedText.Length);


decryptedText.SelectMany(block => BitConverter.GetBytes(new ZZZ(block).GetVal()).Reverse()).ToList().ForEach(byteValue => Console.Write(Encoding.ASCII.GetString(new[] { byteValue })));

但是逻辑可以看懂,可以尝试用C重写一遍代码

但是后面有一个调用zzz

1
2
3
4
5
6
7
8
class ZZZ(ulong val) : ZZY(val)
{
public override ulong GetVal()
{
base.GetVal();
return val + 0x413FD584E295889;
}
}

而ZZZ到A的一万六千行代码都是类似这个的函数

(事后才发现这里调用的代码是base.GetVal()只是调用了继承自ZZY的getval函数然而没有返回值到确定的变量)

那么就需要用一个函数来读取并输出:

1
2
3
4
5
6
7
8
9
10
lines = open('Program.cs','rb').readlines()

a = b'unsigned __int64 (unsigned __int64 val) {\n'
c = b'}'
for line in lines:
if line.startswith(b' return val'):
a += b' val = '+line[18:]
a += c
print(a)
open('c.py','wb').write(a)

然后复制这个函数到解密里面并调用。

最后的代码是

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
#include <stdio.h>
#include <Windows.h>
void dec(unsigned __int64 *a) {
unsigned __int64 b2;
unsigned __int64 b1;
b1 = *a;
b2 = a[1];
unsigned int e = 0x9E3779B9;
unsigned __int64 key[4] = { 0x57656c636f6d6520, 0x746f204e53534354, 0x4620526f756e6423, 0x3136204261736963 };
unsigned __int64 sum = 0;
for (int i = 0; i < 32; ++i)
{
sum += e;
}
for (int i = 0; i < 32; ++i) {

b2 -= (((b1 << 4) ^ (b1 >> 5)) + b1) ^ (sum + key[(sum >> 11) & 3]);
sum -= e;
b1 -= (((b2 << 4) ^ (b2 >> 5)) + b2) ^ (sum + key[sum & 3]);

}
*a = b1;
a[1] = b2;
}
unsigned __int64 ccc(unsigned __int64 val) {
......
return val;
}//写完就5万字了
int main(void) {

unsigned __int64 Q[8] = {
0xc60b34b2bff9d34a, 0xf50af3aa8fd96c6b, 0x680ed11f0c05c4f1, 0x6e83b0a4aaf7c1a3,
0xd69b3d568695c3c5, 0xa88f4ff50a351da2, 0x5cfa195968e1bb5b, 0xc4168018d92196d9
};

for (int k = 0; k < 4; k++)
{
dec(&Q[k*2]);
//sdecrypt(&Q[k * 2], &Q[k * 2 + 1]);

Q[k * 2] = ccc(Q[k * 2]);
Q[k * 2 +1] = ccc(Q[k * 2+1]);
}

for (int i = 0; i < 8; i++)
printf("%#llx,\n", Q[i]);
for (int i = 0; i < 8; i++)
printf("%s", &Q[i]);
getchar();
}
1
2
3
4
5
6
7
8
0x4e53534354467b35,
0x384d745534695478,
0x34754b7538505648,
0x4559795939613774,
0x5a30646171564966,
0x4a5656396b704d52,
0x5a37757644475948,
0x52754a35384d7a7d
1
NSSCTF{58MtU4iTx4uKu8PVHEYyY9a7tZ0daqVIfJVV9kpMRZ7uvDGYHRuJ58Mz}

CRYPTO

pr

打开题

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

flag=plaintext = 'NSSCTF{****************}'
charset = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
padding_length = 100 - len(plaintext)

for _ in range(padding_length):
plaintext += random.choice(charset)

e = 31413537523
message = bytes_to_long(plaintext.encode())
assert message > (1 << 512)
assert message < (1 << 1024)

prime_p = getPrime(512)
prime_q = getPrime(512)
prime_r = getPrime(512)
n1 = prime_p * prime_q
n2 = prime_q * prime_r
ciphertext1 = pow(message, e, n1)
ciphertext2 = pow(message, e, n2)
print('c1=', ciphertext1)
print('c2=', ciphertext2)
print('p=', prime_p)
print('r=', prime_r)


'''
c1= 36918910341116680090654563538246204134840776220077189276689868322808977412566781872132517635399441578464309667998925236488280867210758507758915311644529399878185776345227817559234605958783077866016808605942558810445187434690812992072238407431218047312484354859724174751718700409405142819140636116559320641695
c2= 15601788304485903964195122196382181273808496834343051747331984997977255326224514191280515875796224074672957848566506948553165091090701291545031857563686815297483181025074113978465751897596411324331847008870832527695258040104858667684793196948970048750296571273364559767074262996595282324974180754813257013752
p= 12101696894052331138951718202838643670037274599483776996203693662637821825873973767235442427190607145999472731101517998719984942030184683388441121181962123
r= 10199001137987151966640837133782537428248507382360655526592866939552984259171772190788036403425837649697437126360866173688083643144865107648483668545682383
'''
1
2
3
4
5
6
7
8
过程:
取质数p,q,r
e = ...
n1 = pq
n2 = qr
c1 = m^e mod n1
c2 = m^e mod n2
已知c1,c2,e,p,r求m

根据
$$
\begin{cases}
c_1\equiv m^e(\mod n_1)\\
c_2\equiv m^e(\mod n_2)
\end{cases}
$$
和同余定理
$$
若a-b是n的倍数,那么a和b在\mod n下同余
$$
因为原式可得
$$
\begin{cases}
c_1-m^e=kpq\\
c_2-m^e=kqr
\end{cases}
$$
所以
$$
\begin{cases}
c_1\equiv m^e(\mod p)\\
c_2\equiv m^e(\mod r)
\end{cases}
$$
所以
$$
\begin{cases}
m^e\equiv c_1(\mod p)\\
m^e\equiv c_2(\mod r)
\end{cases}
$$
根据中国剩余定理可以直接求m

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 gmpy2 import invert

# 已知的参数
c1 = 36918910341116680090654563538246204134840776220077189276689868322808977412566781872132517635399441578464309667998925236488280867210758507758915311644529399878185776345227817559234605958783077866016808605942558810445187434690812992072238407431218047312484354859724174751718700409405142819140636116559320641695
c2 = 15601788304485903964195122196382181273808496834343051747331984997977255326224514191280515875796224074672957848566506948553165091090701291545031857563686815297483181025074113978465751897596411324331847008870832527695258040104858667684793196948970048750296571273364559767074262996595282324974180754813257013752
p = 12101696894052331138951718202838643670037274599483776996203693662637821825873973767235442427190607145999472731101517998719984942030184683388441121181962123
r = 10199001137987151966640837133782537428248507382360655526592866939552984259171772190788036403425837649697437126360866173688083643144865107648483668545682383
e = 31413537523

#求n
n = p*r

#求模逆元
j1 = invert(r,p)
j2 = invert(p,r)
#求a
a = c1*j1*r+c2*j2*p
#开方
d = invert(e, (p-1)*(r-1))
last = pow(a,d,n)

print(long_to_bytes(last))
#b'NSSCTF{yUanshEnx1ncHun2o23!}FA3JmflIoai8BxgdIGUQumsNc5R0hpo53zICaiWZRfjBj59P36EwC4CSfJOsZ3LIOYnhUmsQ'