RE

snake

这个题是游戏题,相当于通关就可以得到最后的flag,可惜当时被go的抽象给蒙蔽了双眼,没有想去动调

逻辑大概是:

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
for ( i = 0LL; i < 10; i = v65 + 1 )
{
v65 = i;
snake_pkg_app_Run(20, 20, v0, v1, (_DWORD)v2, v3, v4, v5, v6, v57, v58);
v74 = v8;
v15 = runtime_convT64(v65, 20, v10, v1, (_DWORD)v2, v11, v12, v13, v14, v57);
*(_QWORD *)&v74 = &RTYPE_int;
*((_QWORD *)&v74 + 1) = v15;
v1 = 19;
v2 = &v74;
fmt_Fprintf(
(unsigned int)go_itab__os_File_io_Writer,
os_Stdout,
(unsigned int)"%d Game round ends\n",
19,
(unsigned int)&v74,
1,
1,
v16,
v17,
v57,
v58,
v59,
v60,
v61,
v62,
v63);
}
if ( i == 10 && qword_569E78 == 400 )
{
v73[0] = &RTYPE_string;
v73[1] = &off_4E5D98;
v18 = 1;
LODWORD(v19) = 1;
fmt_Fprintln(
(unsigned int)go_itab__os_File_io_Writer,
os_Stdout,
(unsigned int)v73,
1,
1,
v3,
v4,
v5,
v6,
v57,
v58,
v59,
v60,
v61);
v23 = snake_pkg_game_All_rand;
v71 = snake_pkg_game_All_rand;
v24 = qword_569E78;
v67 = qword_569E78;
v25 = 0LL;
v26 = 0LL;
v27 = 0LL;
while ( v25 < v24 )
{
v66 = v25;
v64 = v26;
v70 = v27;
v28 = *(_QWORD *)(v23 + 8 * v25);
v75 = v8;
v29 = runtime_convT64(v28, v27, v28, v18, v19, v24, v20, v21, v22, v57);
*(_QWORD *)&v75 = &RTYPE_int;
*((_QWORD *)&v75 + 1) = v29;
v18 = fmt_Sprintf((unsigned int)"%02x", 4, (unsigned int)&v75, 1, 1, v30, v31, v32, v33, v57, v58, v59, v60, v61);
v34 = v70;
v39 = runtime_concatstring2(0, v70, v64, v18, 4, v35, v36, v37, v38, v57, v58, v59, v60, v61);
v23 = v71;
v24 = v67;
v19 = v39;
v25 = v66 + 1;
v26 = v34;
v27 = v19;
}
*(_OWORD *)v69.h = v8;
v40 = &v57 + 12;
v56 = &v76;
((void (__fastcall *)(__int64 *))loc_45F36B)(v40);
*(_QWORD *)v69.h = 0xEFCDAB8967452301LL;
*(_QWORD *)&v69.h[2] = 0x1032547698BADCFELL;
v69.h[4] = -1009589776;
*(_OWORD *)&v69.nx = v8;
v46 = (uint8 *)runtime_stringtoslicebyte(
(unsigned int)&v68,
v27,
v41,
(_DWORD)v40,
v19,
v42,
v43,
v44,
v45,
v57,
v58,
v59);
v77.cap = v47;
v77.len = v27;
v77.ptr = v46;
crypto_sha1__ptr_digest_Write(&v69, v77);
v77.ptr = 0LL;
v77.len = 0LL;
v77.cap = 0LL;
v77 = crypto_sha1__ptr_digest_Sum(&v69, v77);
v72 = v8;
v53 = runtime_convTslice(v48, v77.ptr, v77.len, 0, v19, v49, v50, v51, v52, v57, v58, v59);
*(_QWORD *)&v72 = &RTYPE__slice_uint8;
*((_QWORD *)&v72 + 1) = v53;
fmt_Fprintf(
(unsigned int)go_itab__os_File_io_Writer,
os_Stdout,
(unsigned int)"flag{%x}\n",
9,
(unsigned int)&v72,
1,
1,
v54,
v55,
v57,
v58,
v59,
v60,
v61,
v62,
v63);
}

根据汇编,化简逻辑是

1
2
3
4
5
判断i == 10
不是 再来一轮
是 判断qword_569E78 == 400
不是 结束
是 输出flag

以及网上有人说flag是根据输入变换的,但是我动态调试的时候试过不同的发现flag都一样,不过这个代码太抽象我也不知道flag怎么打出来的

最后就是在第一个判断0A的位置下断点,不断改变标志位,让程序到达输出success的位置,最后调用printf

1
flag{da39a3ee5e6b4b0d3255bfef95601890afd80709}

can_can_need_pxory

这个题完全不能理解(现在也是)

是py转exe,先反编译出pyc,然后再反编译成py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
print('ccccccccccccccccccccccccccccccccccc!')
print('D0 U know C?')
print('\n#include <NSSCTF.h>\nv01d bnssst(int FTC[], int lenggggggg) {\n int i, j, SSN;\n')
print('This is CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC')
print('6L+Z5piv5L2g6KaB55qEZmxhZ+WQl++8nwpOU1NDVEZ7YjVlMzlkMDktODg3Yy1hZGI0LTE4OWMtMWI0OGEwNWJmOTY2fQ==')
A = {
'flag': 'NSSCTF{a81c0d5e-ec6d-2b80' }
print('\n SSN = FTC[j];\n printf("flag");\n }\n}\nint mian() {\n int FTC[] = [ -,\n')
print('ccccccccccccccccccc')
print('\nb, 2, 6, 7, -, d, 5, 8, 4, -, 6, 8, 7, 4, -, f, 1, 2, 6, e, 3, a, 5, 1, 0, 6, 1, }];\n int lenggggggg = (int) sizeof(FTC) / sizeof(*FTC);\n bnsScrt(FTC, lenggggggg);\n int i;\n for (i = 0; i < lenggggggg; i++)\n printf("%d ", FTC[i]);\n remake 0;\n}\n')
print('----------------------------------------------------')
import base64
flag = '************************************'
r = ''
for x in range(len(flag)):
if (x + 1) % 4 == 0:
res = str(ord(flag[x]) ^ 2421)
else:
res = str(ord(flag[x]) << 6 << 7 >> 2 >> 1 ^ 92)
r = r + res + ','

print(base64.b64encode(base64.b16encode(base64.b32encode(r.encode('utf-8')))).decode('utf-8'))
print()

上面print出来的东西好像是一段c语言代码,但是语法很抽象,就算改完语法的错,我也不理解ccccccccc是啥玩意,根据后面正常的py语法,怀疑c代码是给最后的末值的,

之后有机会补

CRYPTO

Level_1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from Crypto.Util.number import bytes_to_long, getPrime
from secret import getflag

e1 = getPrime(1024)
e2 = getPrime(1024)
n = e1 * e2
m = bytes_to_long(getflag().encode())
c1 = pow(m, e1, n)
c2 = pow(m, e2, n)
print(n)
print(c1)
print(c2)
print(e1)
print(e2)

这里已知n,c1,c2,e1,e2,把e1,e2看成p,q

那么可以根据$c_1 = m^p \mod n$

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

n = 22517647586235353449147432825948355885962082318127038138351524894369583539246623545565501496312996556897362735789505076324197072008392656511657262430676945685471397862981216472634785622155317188784494912316440866051402627470561626691472280850273482836308002341429493460677206562201947000047718275995355772707947408688836667011206588727438261189233517003341094758634490421007907582147392858070623641389171229435187248184443645883661560636995548332475573072064240073037558031928639832259001407585962782698021735648128101459118863015844905452823095147248865104102562991382119836061161756978764495337874807458182581421229
c1 = 1432393096266401187029059077791766305797845826173887492889260179348416733820890797101745501984437201566364579129066414005659742104885321270122634155922766503333859812540068278962999824043206496595825886026095484801291802992082454776271149083516187121160475839108002133113254134626407840182541809478892306748590016896975053434021666376203540725254480252049443975835307793528287818262102688334515632062552114342619781840154202525919769192765621085008206581226486157149883898548933475155236509073675387541466324512294079413938239828341890576923100769181401944289365386552139418728492565319685207500539721582552448971814
c2 = 13299679392897297864252207869444022461237574801991239380909482153705185317634241850084078027230394830079554676426505967970943836811048777462696506309466535820372917756458083553031417406403895116557560548183674144457502601887632495739472178857537011190162283185735114683172731936834993707871636782206418680404006299140864001776588991141011500807549645227520128216130966268810165946959810884593793452437010902774726405217517557763322690215690606067996057037379898630878638483268362526985225092000670251641184960698506349245915816808028210142606700394584541282682338561482561343076218115042099753144875658666459825545602
e1 = 155861690390761931560700906834977917646203451142415617638229284868013723431003139974975998354830978765979365632120896717380895021936387027045347260400512396388028781862427862974453223157509702913026222541667006325100878113871620322023188372501930117363623076837619478555007555970810681502521309925774889678793
e2 = 144471983652821947847253052623701746810204736865723159569786739658583884214397562204788127484897909964898113250509653721265240138487697822089282456150238116811225975640330930854549232972314642221382625614304415750165289831040623741828600283778523993251940904896081111235859249916040849697146542311990869696453

phi = (e1-1)*(e2-1)
d = gmpy2.invert(e1,phi)
m = pow(c1,d,n)

print(long_to_bytes(m))
#b'NSSCTF{Y0u_Hav3_S01v3d_Crypt0_Leve1_i}'

这就是标准的RSA解密流程

也可以用共模攻击

共模是指:就是明文m,相同。用两个公钥e1,e2加密得到两个私钥d1,d2 和两个密文c1,c2(e不同,n同)
共模攻击,即当m不变的情况下,知道n,e1,e2,c1,c2, 可以在不知道d1,d2的情况下,解出m
利用条件为=> gcd(e1,e2)=1

若两个e互素,gcd(e1,e2)=1

那么一定存在x,y使得gcd(a,b) = ax+by

所以$e_1s_1+e_2s_2=1$

根据复杂的推导过程最后得到:

(c1^s1*c2^s2)%n=m%n=m

即:m = (pow(c_1,s_1,n)*pow(c_2,s_2,n)) % n

所以另一个方法:

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

e1 = 155861690390761931560700906834977917646203451142415617638229284868013723431003139974975998354830978765979365632120896717380895021936387027045347260400512396388028781862427862974453223157509702913026222541667006325100878113871620322023188372501930117363623076837619478555007555970810681502521309925774889678793
e2 = 144471983652821947847253052623701746810204736865723159569786739658583884214397562204788127484897909964898113250509653721265240138487697822089282456150238116811225975640330930854549232972314642221382625614304415750165289831040623741828600283778523993251940904896081111235859249916040849697146542311990869696453
n = 22517647586235353449147432825948355885962082318127038138351524894369583539246623545565501496312996556897362735789505076324197072008392656511657262430676945685471397862981216472634785622155317188784494912316440866051402627470561626691472280850273482836308002341429493460677206562201947000047718275995355772707947408688836667011206588727438261189233517003341094758634490421007907582147392858070623641389171229435187248184443645883661560636995548332475573072064240073037558031928639832259001407585962782698021735648128101459118863015844905452823095147248865104102562991382119836061161756978764495337874807458182581421229
c1 = 1432393096266401187029059077791766305797845826173887492889260179348416733820890797101745501984437201566364579129066414005659742104885321270122634155922766503333859812540068278962999824043206496595825886026095484801291802992082454776271149083516187121160475839108002133113254134626407840182541809478892306748590016896975053434021666376203540725254480252049443975835307793528287818262102688334515632062552114342619781840154202525919769192765621085008206581226486157149883898548933475155236509073675387541466324512294079413938239828341890576923100769181401944289365386552139418728492565319685207500539721582552448971814
c2 = 13299679392897297864252207869444022461237574801991239380909482153705185317634241850084078027230394830079554676426505967970943836811048777462696506309466535820372917756458083553031417406403895116557560548183674144457502601887632495739472178857537011190162283185735114683172731936834993707871636782206418680404006299140864001776588991141011500807549645227520128216130966268810165946959810884593793452437010902774726405217517557763322690215690606067996057037379898630878638483268362526985225092000670251641184960698506349245915816808028210142606700394584541282682338561482561343076218115042099753144875658666459825545602

s,s1,s2=gmpy2.gcdext(e1,e2)
m=(pow(c1,s1,n)*pow(c2,s2,n))%n
print(libnum.n2s(int(m)).decode())

Level_2

1
2
3
4
5
6
7
8
9
10
11
12
# 猜猜我是谁 猜对了直接秒出flag喔
from Crypto.Util.number import bytes_to_long, getPrime
from secret import getflag

p = ***
q = getPrime(1024)
e = 65537
n = p * q
m = bytes_to_long(getflag().encode())
c=pow(m, e, n)
print(q)
print(c)

根据提示说e很常见,盲猜65537

p的取值在ps.txt文件中,遍历p直接求出结果

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

q=145721736470529261146573065574028992352505611489859183763269215489708531333597694809923949026781460438320576519639268582565188719134157402292313959218961804213310847081787824780075530751842057663327444602428455144829447776271394663729996984613471623158126083062443634493708467568220146024273763894704649472957
c=17441814714407189483380175736850663249578989775568187792928771544069162420510939242665830363276698262009780462912108642025299275146709817979705069095332726251759039923303627023610865046363171692163473939115438686877494878334016463787558794121885354719336139401336137097548305393030069499625065664884238710759260231321106291200849044147840392021931720902340003746946851806025722944795391356835342258387797980787437188976704677008092850181043891802072500430200735973581081228711070923822341261809453662427341958883142789220800541626034573952425948295446202775198692920613709157662831071515700549093766182579873408465779
e = 65537


with open('ps.txt', 'r') as f:
ps = [int(line.strip()) for line in f]

for p in ps:
phi = (p-1)*(q-1)
d = gmpy2.invert(e,phi)
m = pow(c,d,p*q)
try:
flag = long_to_bytes(m).decode()
if flag.startswith('NSSCTF{'):
print(flag)
break
except UnicodeDecodeError:
continue

Level_3

当时没做出来,后来发现nc的时候应该输ip 空格 端口 而不是ip:端口

就很亏

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

def decode(n,e1,e2,c1,c2):
t = gmpy2.gcd(e1,e2)
if t == 1:
s,x,y = gmpy2.gcdext(e1,e2)
m = (pow(c1,x,n)*pow(c2,y,n))%n
flag = long_to_bytes(m)
return flag
else:
s,x,y = gmpy2.gcdext(e1,e2)
k = 0
while 1:
m = gmpy2.iroot((pow(c1,x,n)*pow(c2,y,n)+k*n)%n,t)
if m[1]:
print(long_to_bytes(m[0]))
break
else:
k += 1

sh = remote("IP",端口号)

#这里需要666次,试了试665次打不出来
for i in trange(666):
data = sh.recvuntil(b" y0u J01n In th3 NSS t3am?\n py?\n")
n = eval(sh.recvline().decode().strip().split("=")[-1])
e1 = eval(sh.recvline().decode().strip().split("=")[-1])
e2 = eval(sh.recvline().decode().strip().split("=")[-1])
c1 = eval(sh.recvline().decode().strip().split("=")[-1])
c2 = eval(sh.recvline().decode().strip().split("=")[-1])

flag = decode(n,e1,e2,c1,c2)
sh.sendlineafter(b"[+] Pl Give Me flaag :",flag)
sh.interactive()
#转自https://www.cnblogs.com/mumuhhh/p/17993151#top