DASCTF2022 X FATE-奇怪的交易

image-20220426164135626

查一下,upx壳,直接脱壳进行

26

很多都是PYI_PROCNAME,GitHub查一下可以知道这个是pyinstall的

使用objcopy转储pydata部分。这个部分包含pyc (Python字节码)。让我们在一个干净的目录中工作。

这里中文名不好使用,改成atta

1
2
objcopy --dump-section pydata=atta.dump atta
python pyinstxtractor.py atta.dump

https://github.com/extremecoders-re/pyinstxtractor

提取后通过Uncompyle6对pyc文件进行反编译。

https://github.com/rocky/python-uncompyle6/

24

直接对他进行反编译的话是会报错,

把py打包成exe的时候,pyc文件前面的8个字节会被抹掉,所以反编译的时候需要加回来,pyc同目录struct文件前8个字节就是需要的内容。

具体的可以看这一篇文章https://wzt.ac.cn/2019/02/13/pyc-simple/

这里反编译不出来,不知道什么问题,使用pycdc进行反编译

27

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
178
179
180
181
182
183
184
185
from cup import *
if __name__ == '__main__':
flag = input('\xe8\xaf\xb7\xe8\xbe\x93\xe5\x85\xa5flag')
pub_key = [
0x649EE967E7916A825CC9FD3320BEABF263BEAC68C080F52824A0F521EDB6B78577EC52BF1C9E78F4BB71192F9A23F1A17AA76E5979E4D953329D3CA65FB4A71DA57412B59DFD6AEDF0191C5555D3E5F582B81B5E6B23163E9889204A81AFFDF119FE25C92F4ED59BD3285BCD7AAE14824240D2E33C5A97848F4EB7AAC203DE6330D2B4D8FF61691544FBECD120F99A157B3D2F58FA51B2887A9D06CA383C44D071314A12B17928B96F03A06E959A5AFEFA0183664F52CD32B9FC72A04B45913FCB2D5D2D3A415A14F611CF1EAC2D6C785142A8E9CC41B67A6CD85001B06EDB8CA767D367E56E0AE651491BF8A8C17A38A1835DB9E4A9292B1D86D5776C98CC25L,
0x647327833ACFEF1F9C83E74E171FC300FA347D4A6769476C33DA82C95120ACB38B62B33D429206FE6E9BB0BB7AB748A1036971BEA36EC47130B749C1C9FF6FE03D0F7D9FC5346EB0E575BDFA6C530AA57CD676894FC080D2DD049AB59625F4B9C78BCFD95CDCD2793E440E26E189D251121CB6EB177FEDB596409034E8B0C5BBD9BD9342235DBB226C9170EFE347FF0FD2CFF9A1F7B647CC83E4D8F005FD7125A89251C768AFE70BDD54B88116814D5030F499BCAC4673CCCC342FB4B6AC58EA5A64546DC25912B6C430529F6A7F449FD96536DE269D1A1B015A4AC6B6E46EE19DCE8143726A6503E290E4BAE6BD78319B5878981F6CFFDB3B818209341FD68BL]
m = libnum.s2n(flag)
c = str(pow(m, pub_key[1], pub_key[0]))
ᘡ = []
ᘙ = [
0xD28ED952L,
1472742623,
0xD91BA938L,
0xF9F3BD2DL,
0x8EF8E43DL,
617653972,
1474514999,
1471783658,
1012864704,
0xD7821910L,
993855884,
438456717,
0xC83555B7L,
0xE8DFF468L,
198959101,
0xC5B84FEBL,
0xD9F837C6L,
613157871,
0x8EFA4EDDL,
97286225,
0x8B4B608CL,
1471645170,
0xC0B62792L,
583597118,
0xAAB1C22DL,
0xBDB9C266L,
1384330715,
0xAE9F9816L,
0xD1F40B3CL,
0x8206DDC3L,
0xC4E0BADCL,
0xE407BD26L,
145643141,
0x8016C6A5L,
0xAF4AB9D3L,
506798154,
994590281,
0x85082A0BL,
0xCA0BC95AL,
0xA7BE567CL,
1105937096,
1789727804,
0xDFEFB591L,
0x93346B38L,
1162286478,
680814033,
0xAEE1A7A2L,
0x80E574AEL,
0xF154F55FL,
2121620700,
0xFCBDA653L,
0x8E902444L,
0xCA742E12L,
0xB8424071L,
0xB4B15EC2L,
0x943BFA09L,
0xBC97CD93L,
1285603712,
798920280,
0x8B58328FL,
0xF9822360L,
0xD1FD15EEL,
1077514121,
1436444106,
0xA2D6C17EL,
1507202797,
500756149,
198754565,
0x8E014807L,
880454148,
1970517398,
0xBFC6EE25L,
1161840191,
560498076,
1782600856,
0x9D93FEBEL,
1285196205,
788797746,
1195724574,
0xF2174A07L,
103427523,
0x952BFE83L,
0xF730AC4CL,
617564657,
978211984,
1781482121,
0x8379D23AL,
0xEAD737EEL,
0xE41555FBL,
659557668,
0x99F3B244L,
1561884856,
0x842C31A4L,
1189296962,
169145316,
0xA5CE044CL,
1323893433,
824667876,
408202876,
0xE0178482L,
0xF412BBBCL,
1508996065,
162419237,
0xDE740B00L,
0xB7CB64FDL,
0xEBCADB1FL,
0x8EAE2326L,
0x933C216CL,
0xD7D1F649L,
481927014,
0xA448AC16L,
0xBC082807L,
1261069441,
2063238535,
0x8474A61DL,
101459755,
0xBC5654D1L,
1721190841,
1078395785,
176506553,
0xD3C5280FL,
1566142515,
1938949000,
1499289517,
0xC59872F8L,
829714860,
0xE51502A2L,
952932374,
1283577465,
2045007203,
0xEBE6A798L,
0xE09575CDL,
0xADDF4157L,
0xC4770191L,
482297421,
1734231412,
0xDAC71054L,
0x99807E43L,
0xA88D74B1L,
0xCB77E028L,
1533519803,
0xEEEBC3B6L,
0xE7E680E5L,
272960248,
317508587,
0xC4B10CDCL,
0x91776399L,
27470488,
1666674386,
1737927609,
750987808,
0x8E364D8FL,
0xA0985A77L,
562925334,
0x837D6DC3L]
i = 0
if i < len(c):
ᘞ = 0
ᘡ.append(ᘞ)
i += 4
if not i < len(c):
ᘝ = [
54,
54,
54,
54]
ᘠ = len(ᘡ)
res = encrypt(ᘠ, ᘡ, ᘝ)
if ᘡ == ᘙ:
print('You are right!')
input('')
quit()
else:
print('Why not drink a cup of tea and have a rest?')
continue

这里需要一个encrypt,从cup里面导入,这个就是作者自己写的一个库,这里面没有解包解完全,PYZ-00.pyz_extracted是空的,需要在3.10的环境下才可以完成

有-key参数的逆向

逆向前的源码分析

由于Pyinstaller是个开源的包,这也给我们逆向提供了便利

在官方给出的用法中,有给出-key这个参数,说是可以将文件pyc进行一定的压缩加密,以防止被逆向

Pyinstaller这个库本身的打包原理大概就是先将py编译成pyc,然后部分压缩成pyz,程序再通过对pyc和pyz的调用

这个是pyinstaller的打包过程语句

https://bbs.pediy.com/thread-271253.htm

29

根据上面这篇文章的介绍,可以知道archive是加密的一个过程,key在crypto里面

28

30

这里面就是一个tinyaes

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
#!/usr/bin/env python3
import tinyaes
import zlib

CRYPT_BLOCK_SIZE = 16

# 从crypt_key.pyc获取key,也可自行反编译获取
key = bytes('0000000000000tea', 'utf-8')

inf = open('cup.pyc.encrypted', 'rb') # 打开加密文件
outf = open('output.pyc', 'wb') # 输出文件

# 按加密块大小进行读取
iv = inf.read(CRYPT_BLOCK_SIZE)

cipher = tinyaes.AES(key, iv)

# 解密
plaintext = zlib.decompress(cipher.CTR_xcrypt_buffer(inf.read()))

# 补pyc头(最后自己补也行)
outf.write(b'\x6f\x0d\x0d\x0a\0\0\0\0\0\0\0\0\0\0\0\0')

# 写入解密数据
outf.write(plaintext)

inf.close()
outf.close()

反编译出来

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
#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.10

import libnum
from ctypes import *

def MX(z, y, total, key, p, e):
temp1 = (z.value >> 5 ^ y.value << 2) + (y.value >> 3 ^ z.value << 4)
temp2 = (total.value ^ y.value) + (key[p & 3 ^ e.value] ^ z.value)
return c_uint32(temp1 ^ temp2)


def encrypt(ᘗ, ᘖ, ᘘ):
ᘜ = 0x9E3779B9L
ᘛ = 6 + 52 // ᘗ
total = c_uint32(0)
ᘔ = c_uint32(ᘖ[ᘗ - 1])
ᘕ = c_uint32(0)
if ᘛ > 0:
total.value += ᘜ
ᘕ.value = total.value >> 2 & 3
for p in range(ᘗ - 1):
ᘚ = c_uint32(ᘖ[p + 1])
ᘖ[p] = c_uint32(ᘖ[p] + MX(ᘔ, ᘚ, total, ᘘ, p, ᘕ).value).value
ᘔ.value = ᘖ[p]
ᘚ = c_uint32(ᘖ[0])
ᘖ[ᘗ - 1] = c_uint32(ᘖ[ᘗ - 1] + MX(ᘔ, ᘚ, total, ᘘ, ᘗ - 1, ᘕ).value).value
ᘔ.value = ᘖ[ᘗ - 1]
ᘛ -= 1
if not ᘛ > 0:
return


一眼xxtea,直接带入求解

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
#include <stdio.h>
#include <stdint.h>

#define KEYLEN 4
#define DELTA 0x9e3779b9
#define LUN 32

void Encrypt(unsigned int * v, unsigned int * k);
void Decrypt(unsigned int * v, unsigned int * k);

#define MX (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (key[(p&3)^e] ^ z)))

void btea(uint32_t *v, int n, uint32_t const key[4])
{
uint32_t y, z, sum;
unsigned p, rounds, e;
if (n > 1) /* Coding Part */
{
rounds = 6 + 52/n;
sum = 0;
z = v[n-1];
do
{
sum += DELTA;
e = (sum >> 2) & 3;
for (p=0; p<n-1; p++)
{
y = v[p+1];
z = v[p] += MX;
}
y = v[0];
z = v[n-1] += MX;
}
while (--rounds);
}
else if (n < -1) /* Decoding Part */
{
n = -n;
rounds = 6 + 52/n;
sum = rounds*DELTA;
y = v[0];
do
{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--)
{
z = v[p-1];
y = v[p] -= MX;
}
z = v[n-1];
y = v[0] -= MX;
sum -= DELTA;
}
while (--rounds);
}
}



int main(void)
{
uint32_t v[] = { 0xD28ED952, 1472742623, 0xD91BA938, 0xF9F3BD2D, 0x8EF8E43D, 617653972, 1474514999, 1471783658, 1012864704, 0xD7821910, 993855884, 438456717, 0xC83555B7, 0xE8DFF468, 198959101, 0xC5B84FEB, 0xD9F837C6, 613157871, 0x8EFA4EDD, 97286225, 0x8B4B608C, 1471645170, 0xC0B62792, 583597118, 0xAAB1C22D, 0xBDB9C266, 1384330715, 0xAE9F9816, 0xD1F40B3C, 0x8206DDC3, 0xC4E0BADC, 0xE407BD26, 145643141, 0x8016C6A5, 0xAF4AB9D3, 506798154, 994590281, 0x85082A0B, 0xCA0BC95A, 0xA7BE567C, 1105937096, 1789727804, 0xDFEFB591, 0x93346B38, 1162286478, 680814033, 0xAEE1A7A2, 0x80E574AE, 0xF154F55F, 2121620700, 0xFCBDA653, 0x8E902444, 0xCA742E12, 0xB8424071, 0xB4B15EC2, 0x943BFA09, 0xBC97CD93, 1285603712, 798920280, 0x8B58328F, 0xF9822360, 0xD1FD15EE, 1077514121, 1436444106, 0xA2D6C17E, 1507202797, 500756149, 198754565, 0x8E014807, 880454148, 1970517398, 0xBFC6EE25, 1161840191, 560498076, 1782600856, 0x9D93FEBE, 1285196205, 788797746, 1195724574, 0xF2174A07, 103427523, 0x952BFE83, 0xF730AC4C, 617564657, 978211984, 1781482121, 0x8379D23A, 0xEAD737EE, 0xE41555FB, 659557668, 0x99F3B244, 1561884856, 0x842C31A4, 1189296962, 169145316, 0xA5CE044C, 1323893433, 824667876, 408202876, 0xE0178482, 0xF412BBBC, 1508996065, 162419237, 0xDE740B00, 0xB7CB64FD, 0xEBCADB1F, 0x8EAE2326, 0x933C216C, 0xD7D1F649, 481927014, 0xA448AC16, 0xBC082807, 1261069441, 2063238535, 0x8474A61D, 101459755, 0xBC5654D1, 1721190841, 1078395785, 176506553, 0xD3C5280F, 1566142515, 1938949000, 1499289517, 0xC59872F8, 829714860, 0xE51502A2, 952932374, 1283577465, 2045007203, 0xEBE6A798, 0xE09575CD, 0xADDF4157, 0xC4770191, 482297421, 1734231412, 0xDAC71054, 0x99807E43, 0xA88D74B1, 0xCB77E028, 1533519803, 0xEEEBC3B6, 0xE7E680E5, 272960248, 317508587, 0xC4B10CDC, 0x91776399, 27470488, 1666674386, 1737927609, 750987808, 0x8E364D8F, 0xA0985A77, 562925334, 0x837D6DC3, 0 }, k[KEYLEN] = { 54, 54, 54, 54 };
int i, index;
int n = 155;

btea(v, -n, k);
unsigned char * p = (unsigned char *)v;
for ( i = 0, index = 0; index < n; i += 4, index++ )
printf("%c%c%c%c", p[i + 3], p[i + 2], p[i + 1], p[i]);

return 0;
}
//10610336534759505889607399322387179316771488492347274741918862678692508953185876570981227584004676580623553664818853686933004290078153620168054665086468417541382824708104480882577200529822968531743002301934310349005341104696887943182074473298650903541494918266823037984054778903666406545980557074219162536057146090758158128189406073809226361445046225524917089434897957301396534515964547462425719205819342172669899546965221084098690893672595962129879041507903210851706793788311452973769358455761907303633956322972510500253009083922781934406731633755418753858930476576720874219359466503538931371444470303193503733920039

最后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
39
40
41
42
43
44
45
import gmpy2
import libnum

def continuedFra(x, y):
cf = []
while y:
cf.append(x // y)
x, y = y, x % y
return cf
def gradualFra(cf):
numerator = 0
denominator = 1
for x in cf[::-1]:
# 这里的渐进分数分子分母要分开
numerator, denominator = denominator, x * denominator + numerator
return numerator, denominator
def solve_pq(a, b, c):
par = gmpy2.isqrt(b * b - 4 * a * c)
return (-b + par) // (2 * a), (-b - par) // (2 * a)
def getGradualFra(cf):
gf = []
for i in range(1, len(cf) + 1):
gf.append(gradualFra(cf[:i]))
return gf


def wienerAttack(e, n):
cf = continuedFra(e, n)
gf = getGradualFra(cf)
for d, k in gf:
if k == 0: continue
if (e * d - 1) % k != 0:
continue
phi = (e * d - 1) // k
p, q = solve_pq(1, n - phi + 1, n)
if p * q == n:
return d


n=12702192797044914024075774649965354105344232304099465264316470282606351700311177624703682814557100043599414982439635470829841890299241342602374578366076034128412992290094164613120745611751102797279925764448133764246126488845600641524814194290745105708735258127757986238766868988676022258542038318776640732920027324986285887310132372524224961045858183153047991881042129131551711617627844146600513830709959185824512201669420128585170924683844128155435146399996585220865423125338735154727569986267948480523307784641442521735105741341230032585576300299944879647981670048377150556292280650846158185797588466680532743801893
e=12680615221091469696163926483122992106481999501435284497098601343706982733487916553201934931961274845294041438909951977672521864927961654544622905443692482152403380984734291652023321187458458985625147422841102922314725726207365632256563373977251725785357590588556314671253970422319546403985257810950046085994573229162322957630767327089195523762665081311711474689269184996318744510300057603532953644164998953897411177604349567514705039306693117602798453972917348902600111420473965929048876821563646206875034926505783009957256212261250539005023918242209009676914632796839852778318989278092929214021282438144809708279435
c=10610336534759505889607399322387179316771488492347274741918862678692508953185876570981227584004676580623553664818853686933004290078153620168054665086468417541382824708104480882577200529822968531743002301934310349005341104696887943182074473298650903541494918266823037984054778903666406545980557074219162536057146090758158128189406073809226361445046225524917089434897957301396534515964547462425719205819342172669899546965221084098690893672595962129879041507903210851706793788311452973769358455761907303633956322972510500253009083922781934406731633755418753858930476576720874219359466503538931371444470303193503733920039
d=wienerAttack(e, n)
m=pow(c, d, n)
print(libnum.n2s(m).decode())