20210830-DAS8月赛-CryptoSecWriteUp

 

Crypto

easymath

1
2
3
assert(len(open('flag.txt', 'rb').read()) < 50)
assert(str(int.from_bytes(open('flag.txt', 'rb').read(), byteorder='big') << 10000).endswith(
'1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008'))

代码很短,也可以直接搜到原题

bytesorder='big'可以理解是正常的顺序

主要是觉得很神奇,左移10000位,然后只告诉了低579位,真的可以还原吗?

不过用数学语言来表达就习惯多了
$$
c=flag\times 2^{10000}\ mod\ 10^{175}\notag
$$
相当于取了个余;只要求出$2^{10000}$在模$10^{175}$下的逆元就行,这不是有手就行,但显然这个逆元并不存在,但问题不大,稍微变一下
$$
c=flag\times 2^{10000}\ mod\ 5^{175}\notag
$$


因为有性质,如果$a\equiv b\ (mod\ n),\ a\equiv b\ (mod\ m),\ (m, n)=1$,则$a\equiv b(mod\ mn)$


感觉反着来也成立的吧,显然$(2^{175},\ 5^{175})=1$

1
2
3
4
5
6
7
8
9
10
from Crypto.Util.number import *
from gmpy2 import *

n = 5 ** 175
c = 1862790884563160582365888530869690397667546628710795031544304378154769559410473276482265448754388655981091313419549689169381115573539422545933044902527020209259938095466283008
c = c
phi = 5 ** 174
e = 2 ** 10000
d = invert(e, n)
print(long_to_bytes(c * d % n))

ezRSA

直接转化成等于的形式,然后取个gcd,因为取出来可能不是正好是n和p,所以用分解攻击factordb剔除小因子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#!/usr/bin/env sage
# -*- coding: utf-8 -*-
from Crypto.Util.number import *

plain1 = 3796374001
cipher1 = 10814407739419442187905858785036186878265127046318055454993453460552141704269761831133605965488334657725928223663072928135729092442048892277444747664105855191494328013597494843840801624660190005877515193495251116322331333145225214492628388272052283297261629247983765384231471683884012700575979269960065526415802023634510913009036934242220680865773837250316443624988133196570064551438174112950794689256211630478109685814880608384948776450292755634359375937804770120858228075005653177911703351120582838064680054557165091424216996781206537691443956931890710761301856045586473958014856501026856223946554632634123695548179
plain2 = 4274439796
cipher2 = 87226798597265930735797832586236279967789468186786741246367414679613517601654025942029826295922574046522178393263827646913102970456195019295401416652274787934598801006209685121040719655143935749480878915637540137699100422932935519357118466505812144970497483991623024823375063776302868706571808198638413485212863316779488625319157322436072639726910982871292474427111853478193221459564153774349503133897947087219144794655871631028877397232372688447849203202066982834256420368807780090246093374914035033275326840206150648030439511140807548259558987343365751983159445433804444373606478977126329710773866415852267322001
plain3 = 3325291543
cipher3 = 9382727308462526071828291861625444755821341794212101844314359460079432045375739882063652976611283182057033881092525502333782051326520856709162727825183042333495142759484340360567209663928461296371430651153068234201274220444046746723715852931539307137462642852266744794350148429783596186264775135674497726336356558991142315096962405777053398974439740872315007701981484005150026915096332916499718849929261683668753849212760142928383699802276667736418472263282318556853006287601969938973761042341846844526359073801116843895009315716346895596793683181704835335051683309743931741006154082213663428178283831538866255884755
plain4 = 1344652736
cipher4 = 4321964026676773781748104809247153356237715067039867231031624087256207483823813596319043458347848480918702592529113491431289681396399509022324524505867856178311958890363168588728856811216344821674576551978795805425938895529979965804450330107190184989162075120112336133813443406172261019202954524704870212620162773467949822492505161759519710435619043135693162949516270801813957833639117255071409629966835262468558867355399456489652824578176999147239152024128878816180401772196756218195440508847291475372211289300191672193680292568402473128269561454972660235893426215596184157205084579301349999511988743927089317168711
c = 7676870019429280974392994820719779231294040954319033563743135447473572416831050516949578774541281865709413894823796173396916557712257817949278444474172193939467995392598453462557057904995693840979847693206445078435907817047607948884368740596897139479299803522434307154541548742050088306413312454547460881877229439237898277933224023743845054110141568593673519203476919586868299617487091772845879027851695029674390129630380608842037317291970843742534837090616445063709778227810263198355145168049129671663511533431798983910771539362325095830241252453404715144468588527605118717772056998732396545216696090692231228929195
e = 0x10001
n = gcd(plain1**e-cipher1, plain3**e-cipher3) // 2
p = gcd(plain2**e-cipher2, plain4**e-cipher4) // 65
print(long_to_bytes(pow(c, invert(e, (p-1)*(q-1)), n)))

let’s play with rsa~

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 sympy import isprime,nextprime
from Crypto.Util.number import getPrime as getprime ,long_to_bytes,bytes_to_long,inverse
flag='flag{***************}'

def play():
p=getprime(1024)
q=getprime(1024)

n=p*q
e=65537

print "Hello,let's play rsa~\n"
print 'Now,I make some numbers,wait a second\n'
n1=getprime(200)
n2=getprime(200)
number=n1*n2
print "Ok,i will send two numbers to you,one of them was encoded.\n"
print "Encode n1:%d,\n"%(pow(n1,e,n))
print "And n2:%d.\n"%n2

print "Information that can now be made public:the public key (n,e):(%d,%d)\n"%(n,e)
while True:
try:
c=int(raw_input("ok,now,tell me the value of the number (encode it for safe):"))
except:
print "Sorry,the input is illeagal, and the integer is accept~"
else:
break
d=inverse(e,(p-1)*(q-1))
m=pow(c,d,n)
if m==number:
print "It's easy and interesting,didn't it?\n"
print "This is the gift for you :"+flag
else:
print "Emmmmm,there is something wrong, bye~\n"

if __name__ == '__main__':
play()

简单性质的应用,想让我们给出$c=(n_1\times n_2)^e\ mod\ n$,提供了n和e,以及$c_1=n_1^e\ mod\ n$和$n_2$
$$
c=(n_1^e\ mod\ n\cdot n_2^e\ mod\ n)\ mod\ n=(c_1\cdot n_2^e\ mod\ n)\ mod\ n\notag
$$

Re

py

看出的人比较多,想肯定有原题,然后就搜到了这位师傅的博客,逆向ctf-2020湖湘杯Re_03,一些python的反编译操作

首先用PE工具看下

image-20210830152655257

不知道哪里不对,但是用PEiD看,会告诉你是一个无效的exe文件

image-20210830152749825

说是用python打包的exe文件,反编译一下,使用github的pyinstxtractor.py工具

python pyinstxtractor.py py.exe

会得到一个文件夹,需要关注没有后缀名的pystruct,用查看内码的软件打开,将struct文件开头和py不一样的代码给拷贝到py处,保存成.pyc文件

然后用uncompyle6反编译的成源文件,直接用pip install uncompyle即可安装

uncompyle6 py.pyc py.py

得到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def encode(s):
str = ''
for i in range(len(s)):
res = ord(s[i]) ^ 32
res += 31
str += chr(res)

return str


m = 'ek`fz13b3c5e047b`bd`0/c268e600e7c5d1`|'
strings = ''
strings = input('Input:')
if encode(strings) == m:
print 'Correct!'
else:
print 'Try again!'

然后逆回去就好了

apkrev(not solve)

用模拟器打开,发现要输入一个注册码,然后安卓逆向工具去分析,找到MainActivity中的onClick,发现关键的函数myCheck被隐藏了,搜了下,藏在.so文件里了,所以将.apk改成.zip然后解压找到

说是类似RC4的流密码

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
175
176
177
__int64 __fastcall Java_com_example_re_MainActivity_myCheck(__int64 a1, __int64 a2, __int64 a3)
{
const char *v3; // x20
unsigned __int64 v4; // x0
__int64 v5; // x19
char *v6; // x21
unsigned __int64 v7; // x22
char v8; // w21
void *v9; // x19
const char *v10; // x20
size_t v11; // w0
unsigned int v12; // w20
_DWORD *v13; // x0
int32x4_t v14; // q0
__int64 v15; // x8
int32x4_t v16; // q1
int32x4_t v17; // q2
char *v18; // x9
int32x4_t v19; // q3
__int64 v20; // x8
unsigned __int8 v21; // w11
int v22; // w9
char *v23; // x10
int v24; // w13
char *v25; // x14
__int64 v26; // x9
__int64 v27; // x10
__int64 v28; // x8
char *v29; // x12
int v30; // w14
int v31; // w16
__int64 v32; // x9
unsigned __int64 v34; // [xsp+8h] [xbp-268h] BYREF
__int64 v35; // [xsp+10h] [xbp-260h]
char *v36; // [xsp+18h] [xbp-258h]
__int128 dest[33]; // [xsp+20h] [xbp-250h] BYREF

_ReadStatusReg(ARM64_SYSREG(3, 3, 13, 0, 2));
v3 = (const char *)(*(__int64 (__fastcall **)(__int64, __int64, _QWORD))(*(_QWORD *)a1 + 1352LL))(a1, a3, 0LL);
v34 = 0LL;
v35 = 0LL;
v36 = 0LL;
v4 = strlen(v3);
v5 = v4;
if ( v4 >= 0x17 )
{
v7 = (v4 + 16) & 0xFFFFFFFFFFFFFFF0LL;
v6 = (char *)operator new(v7);
v35 = v5;
v36 = v6;
v34 = v7 | 1;
goto LABEL_5;
}
v6 = (char *)&v34 + 1;
LOBYTE(v34) = 2 * v4;
if ( v4 )
LABEL_5:
memcpy(v6, v3, v5);
v6[v5] = 0;
dest[30] = 0u;
dest[31] = 0u;
dest[28] = 0u;
dest[29] = 0u;
dest[26] = 0u;
dest[27] = 0u;
dest[24] = 0u;
dest[25] = 0u;
dest[22] = 0u;
dest[23] = 0u;
dest[20] = 0u;
dest[21] = 0u;
dest[18] = 0u;
dest[19] = 0u;
dest[16] = 0u;
dest[17] = 0u;
dest[14] = 0u;
dest[15] = 0u;
dest[12] = 0u;
dest[13] = 0u;
dest[10] = 0u;
dest[11] = 0u;
dest[8] = 0u;
dest[9] = 0u;
dest[7] = 0u;
dest[5] = 0u;
dest[6] = 0u;
dest[3] = 0u;
dest[4] = 0u;
dest[1] = 0u;
dest[2] = 0u;
dest[0] = 0u;
fflush(&_sF);
v8 = v34;
v9 = v36;
if ( (v34 & 1) != 0 )
v10 = v36;
else
v10 = (char *)&v34 + 1;
v11 = strlen(v10);
memcpy(dest, v10, v11);
v12 = 0;
if ( strlen((const char *)dest) != 32LL )
{
LABEL_23:
if ( (v8 & 1) == 0 )
return v12;
LABEL_24:
operator delete(v9);
return v12;
}
v13 = malloc(0x408u);
v14 = (int32x4_t)xmmword_29F00;
v15 = 0LL;
v16.n128_u64[0] = 0x400000004LL;
v16.n128_u64[1] = 0x400000004LL;
v17.n128_u64[0] = 0x800000008LL;
v17.n128_u64[1] = 0x800000008LL;
*(_QWORD *)v13 = 0LL;
do
{
v18 = (char *)&v13[v15];
v15 += 8LL;
v19 = vaddq_s32(v14, v16);
*(int32x4_t *)(v18 + 8) = v14;
v14 = vaddq_s32(v14, v17);
*(int32x4_t *)(v18 + 24) = v19;
}
while ( v15 != 256 );
v20 = 0LL;
v21 = 0;
v22 = 0;
v23 = (char *)(v13 + 2);
do
{
v24 = *(_DWORD *)&v23[v20];
v21 += a12345678[v22] + v24;
v25 = (char *)&v13[v21];
if ( v22 + 1 < 8 )
++v22;
else
v22 = 0;
*(_DWORD *)&v23[v20] = *((_DWORD *)v25 + 2);
v20 += 4LL;
*((_DWORD *)v25 + 2) = v24;
}
while ( v20 != 1024 );
v26 = 0LL;
LOBYTE(v27) = 0;
LOBYTE(v28) = 0;
do
{
v27 = (unsigned __int8)(v27 + 1);
v29 = (char *)(v13 + 2);
v30 = v13[v27 + 2];
v28 = (unsigned __int8)(v30 + v28);
v31 = v13[v28 + 2];
*(_DWORD *)&v29[4 * v27] = v31;
*(_DWORD *)&v29[4 * v28] = v30;
*((_BYTE *)dest + v26++) ^= LOBYTE(v13[(unsigned __int8)(v31 + v30) + 2]);
}
while ( v26 != 32 );
*v13 = v27;
v13[1] = v28;
v32 = 0LL;
while ( *((unsigned __int8 *)dest + v32) == enc[v32] )
{
if ( (unsigned __int64)++v32 > 0x1F )
{
v12 = 1;
goto LABEL_23;
}
}
v12 = 0;
if ( (v8 & 1) != 0 )
goto LABEL_24;
return v12;
}

窝好累