春秋杯 逆向 wp

First Post:

Last Update:

sum

main函数:

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
int __cdecl main(int argc, const char **argv, const char **envp)
{
char *v3; // rbp
int v4; // r14d
unsigned int v5; // r12d
__int64 i; // rbx
char v7; // al
int v8; // eax
const char *v9; // rax

v3 = (char *)&matrix;
v4 = 1;
v5 = 0;
puts("Welcome to Solver!");
do
{
for ( i = 0LL; i != 9; ++i )
{
if ( !v3[i] )
{
v7 = getchar();
if ( (unsigned __int8)(v7 - 49) > 8u )
v4 = 0;
else
v3[i] = v7 - 48;
}
v8 = v3[i];
v5 += v8;
}
v3 += 9;
}
while ( v3 != (char *)&matrix + 81 );
if ( v4 && (unsigned int)verify("Welcome to Solver!", argv) )
{
puts("You Win!");
__snprintf_chk(buf, 32LL, 1LL, 32LL, "%d", v5);
v9 = (const char *)str2md5(buf, strlen(buf));
__printf_chk(1LL, "flag is: flag{%s}\n\n", v9);
exit(0);
}
puts("Again~");
return 0;
}

首先是一个do while嵌套for的一个81次的循环,循环时当v3[i]的值等于0,会让用户输入一个字符,并且该输入必须在0-9之间

那么接下来进入verify函数:

不仔细看的话中等复杂,但他肯定是一段验证程序,因为它在if条件里嘛,满足条件就是win了。分析的话要么动调,要么为了省事直接问gpt(这个题效果还不错,有时候小心他会胡说八道):

solve:

知道是数独,提取出81个数据,找个在线网站解一下数独,再运行程序填进去flag就输出了

Poisoned_tea_CHELL

要么脱了壳看,动调也行,就是个xtea,当时的脚本丢了,懒得找了

BWBA

加密算法是DCT离散余弦变换,

但是比赛时候认为这个算法是不可逆的,所以用了z3来解这个值

方程生成:

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
#include<bits/stdc++.h>
#include <cmath>
using namespace std;
double a1[64] = {0};
int main()
{
double flag[64] = {370.75,234.362,-58.0834,59.8212,88.8221,-30.2406,21.8316,49.9781,-33.5259,2.69675,43.5386,-30.2925,-28.0754,27.593,-2.53962,-27.1883,-5.60777,-0.263937,6.80326,8.03022,-6.34681,-0.89506,-6.80685,-13.6088,27.0958,29.8439,-21.7688,-20.6925,-13.2155,-37.0994,2.23679,37.6699,-3.5,9.85188,57.2806,13.5715,-20.7184,8.6816,3.59369,-4.5302,4.22203,-28.8166,-23.695,31.2268,6.58823,-39.9966,-20.7877,-19.7624,-22.031,16.3285,2.07557,-26.2521,16.1914,18.3976,-26.9295,3.03769,41.0412,20.2598,14.991,6.99392,-22.3752,-7.24466,8.96299,-10.4874}, v10 = 0, v9 = 0;
int i, j, cnt = 64;
for ( i = 0; i < cnt; ++i )
{
cout <<endl <<"s.add((";
double tempi = i;
for ( j = 0; j < cnt; ++j )
{
double tempj = j;
v9 = cos((tempj + 0.5) * (3.141592653589793 * tempi) / cnt);
if (j == 63){
cout <<"(";
printf("%lf",v9);
cout<<" * flag" <<j<<")";
}
else{
cout <<"(";
printf("%lf",v9);
cout<<" * flag" <<j<<")" <<"+";
}
}
if ( i )
v10 = sqrt(2.0 / cnt);
else
v10 = sqrt(1.0 / cnt);
flag[i] /= v10;
cout <<")";
cout <<" ==";
printf("%lf",flag[i]);
//

cout<<")";
}
}

z3:

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

flag0 = Real('flag0')
flag1 = Real('flag1')
flag2 = Real('flag2')
flag3 = Real('flag3')

# ...

flag63 = Real('flag63')
s = Solver()

s.add(((1.000000 * flag0)+(1.000000 * flag1)+(1.000000 * flag2)+(1.000000 * flag3)+(1.000000 * flag4)+(1.000000 * flag5)+(1.000000 * flag6)+(1.000000 * flag7)+(1.000000 * flag8)+(1.000000 * flag9)+(1.000000 * flag10)+(1.000000 * flag11)+(1.000000 * flag12)+(1.000000 * flag13)+(1.000000 * flag14)+(1.000000 * flag15)+(1.000000 * flag16)+(1.000000 * flag17)+(1.000000 * flag18)+(1.000000 * flag19)+(1.000000 * flag20)+(1.000000 * flag21)+(1.000000 * flag22)+(1.000000 * flag23)+(1.000000 * flag24)+(1.000000 * flag25)+(1.000000 * flag26)+(1.000000 * flag27)+(1.000000 * flag28)+(1.000000 * flag29)+(1.000000 * flag30)+(1.000000 * flag31)+(1.000000 * flag32)+(1.000000 * flag33)+(1.000000 * flag34)+(1.000000 * flag35)+(1.000000 * flag36)+(1.000000 * flag37)+(1.000000 * flag38)+(1.000000 * flag39)+(1.000000 * flag40)+(1.000000 * flag41)+(1.000000 * flag42)+(1.000000 * flag43)+(1.000000 * flag44)+(1.000000 * flag45)+(1.000000 * flag46)+(1.000000 * flag47)+(1.000000 * flag48)+(1.000000 * flag49)+(1.000000 * flag50)+(1.000000 * flag51)+(1.000000 * flag52)+(1.000000 * flag53)+(1.000000 * flag54)+(1.000000 * flag55)+(1.000000 * flag56)+(1.000000 * flag57)+(1.000000 * flag58)+(1.000000 * flag59)+(1.000000 * flag60)+(1.000000 * flag61)+(1.000000 * flag62)+(1.000000 * flag63)) ==2966.000000)
s.add(((0.999699 * flag0)+(0.997290 * flag1)+(0.992480 * flag2)+(0.985278 * flag3)+(0.975702 * flag4)+(0.963776 * flag5)+(0.949528 * flag6)+(0.932993 * flag7)+(0.914210 * flag8)+(0.893224 * flag9)+(0.870087 * flag10)+(0.844854 * flag11)+(0.817585 * flag12)+(0.788346 * flag13)+(0.757209 * flag14)+(0.724247 * flag15)+(0.689541 * flag16)+(0.653173 * flag17)+(0.615232 * flag18)+(0.575808 * flag19)+(0.534998 * flag20)+(0.492898 * flag21)+(0.449611 * flag22)+(0.405241 * flag23)+(0.359895 * flag24)+(0.313682 * flag25)+(0.266713 * flag26)+(0.219101 * flag27)+(0.170962 * flag28)+(0.122411 * flag29)+(0.073565 * flag30)+(0.024541 * flag31)+(-0.024541 * flag32)+(-0.073565 * flag33)+(-0.122411 * flag34)+(-0.170962 * flag35)+(-0.219101 * flag36)+(-0.266713 * flag37)+(-0.313682 * flag38)+(-0.359895 * flag39)+(-0.405241 * flag40)+(-0.449611 * flag41)+(-0.492898 * flag42)+(-0.534998 * flag43)+(-0.575808 * flag44)+(-0.615232 * flag45)+(-0.653173 * flag46)+(-0.689541 * flag47)+(-0.724247 * flag48)+(-0.757209 * flag49)+(-0.788346 * flag50)+(-0.817585 * flag51)+(-0.844854 * flag52)+(-0.870087 * flag53)+(-0.893224 * flag54)+(-0.914210 * flag55)+(-0.932993 * flag56)+(-0.949528 * flag57)+(-0.963776 * flag58)+(-0.975702 * flag59)+(-0.985278 * flag60)+(-0.992480 * flag61)+(-0.997290 * flag62)+(-0.999699 * flag63)) ==1325.751676)

# ...

s.add(((0.024541 * flag0)+(-0.073565 * flag1)+(0.122411 * flag2)+(-0.170962 * flag3)+(0.219101 * flag4)+(-0.266713 * flag5)+(0.313682 * flag6)+(-0.359895 * flag7)+(0.405241 * flag8)+(-0.449611 * flag9)+(0.492898 * flag10)+(-0.534998 * flag11)+(0.575808 * flag12)+(-0.615232 * flag13)+(0.653173 * flag14)+(-0.689541 * flag15)+(0.724247 * flag16)+(-0.757209 * flag17)+(0.788346 * flag18)+(-0.817585 * flag19)+(0.844854 * flag20)+(-0.870087 * flag21)+(0.893224 * flag22)+(-0.914210 * flag23)+(0.932993 * flag24)+(-0.949528 * flag25)+(0.963776 * flag26)+(-0.975702 * flag27)+(0.985278 * flag28)+(-0.992480 * flag29)+(0.997290 * flag30)+(-0.999699 * flag31)+(0.999699 * flag32)+(-0.997290 * flag33)+(0.992480 * flag34)+(-0.985278 * flag35)+(0.975702 * flag36)+(-0.963776 * flag37)+(0.949528 * flag38)+(-0.932993 * flag39)+(0.914210 * flag40)+(-0.893224 * flag41)+(0.870087 * flag42)+(-0.844854 * flag43)+(0.817585 * flag44)+(-0.788346 * flag45)+(0.757209 * flag46)+(-0.724247 * flag47)+(0.689541 * flag48)+(-0.653173 * flag49)+(0.615232 * flag50)+(-0.575808 * flag51)+(0.534998 * flag52)+(-0.492898 * flag53)+(0.449611 * flag54)+(-0.405241 * flag55)+(0.359895 * flag56)+(-0.313682 * flag57)+(0.266713 * flag58)+(-0.219101 * flag59)+(0.170962 * flag60)+(-0.122411 * flag61)+(0.073565 * flag62)+(-0.024541 * flag63)) ==-59.325693)

print(s.check())
print(s.model())

注意z3的小数都是用分数表示的,精度不重要,大概就行了,取整输出就是flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
flag = [0 for i in range(64)]
flag[
55] = 221527137955783113048387578098669691852696472163174363992368587140468072862920727666475906867404888638838351318494490704211264388450373808157143523413409650950475194124966447357784178278474314607876795718871850895314347485314725170589326708258271512005230085206855375465185961941426128822017371048964561623152284829085198599876666124694211060913327259311235999626439130457424039519987122749459176262 / 4393949489366013141326163371687704628053876930668323418191072958216729857094949839067603311586792854232854294729192049148923892216475097051452982099673208220975632436415151212496411611956992817991807078659939201284753446394195432061555651948215760845094198788857248533383339796074398574229674880933341286069968842091882649229346271093965887550163210225244116603976086342392436567094267576310818570886085
flag[
32] = 1687279396917760686256775837450156537810376211966209118713889456264098294438023380830097733539434047032147127492810004743931813776323691257487629314860358703386692057998366248033741285251060976444886928995003306048059584076838156029948315773458988690200028145397390874043032135199067245841270264782772413546558083597284157959212565958078116842012101046869288077937458487761020750491219956365179541224993959 / 35151595914928105130609306973501637024431015445346587345528583665733838856759598712540826492694342833862834357833536393191391137731800776411623856797385665767805059491321209699971292895655942543934456629279513610278027571153563456492445215585726086760753590310857988267066718368595188593837399047466730288559750736735061193834770168751727100401305681801952932831808690739139492536754140610486548567088680


# ...

flag[
26] = 7170921423120406134452068759100082419053673782981918591779303332725381751713223477702469650712602475303035621426578259606409522642372892852081452455753207582821725938452118491738552068892503760852475907805364856515936237811647835538337671975355462756861657530521173108999585739612050593385888410823160809684081128580452765679381516405015784498511345136923293313107025304624821870346710591020483644332361041 / 70303191829856210261218613947003274048862030890693174691057167331467677713519197425081652985388685667725668715667072786382782275463601552823247713594771331535610118982642419399942585791311885087868913258559027220556055142307126912984890431171452173521507180621715976534133436737190377187674798094933460577119501473470122387669540337503454200802611363603905865663617381478278985073508281220973097134177360
flag[
16] = 861213459618800635980908762431887453130690039744021489676272811252339111506547068326575312581482641230115288118062762058810601836638224532023901869148002712207608878099715831214905749629077894633991833351216771043843037338219613551234098593505551504978788179664358071455377274133270389363464604100908033564647036460300697073894865437645538471236181203672538362517067280984107395984610847492259850454653687 / 17575797957464052565304653486750818512215507722673293672764291832866919428379799356270413246347171416931417178916768196595695568865900388205811928398692832883902529745660604849985646447827971271967228314639756805139013785576781728246222607792863043380376795155428994133533359184297594296918699523733365144279875368367530596917385084375863550200652840900976466415904345369569746268377070305243274283544340
flag[
50] = 5389532113412151751299492060732273506518184376927034892632825060270115663910131858165879826910364623085516402239499563714301946910479121309695970873212193419808425757856749399267199805874274962872794906415079644252333229564204011386698056058032425290562078339180963131641291131179791821069055657674420630383090229680767184468506535062020111993855418757917802204733786495755701316418542412964134684989 / 70303191829856210261218613947003274048862030890693174691057167331467677713519197425081652985388685667725668715667072786382782275463601552823247713594771331535610118982642419399942585791311885087868913258559027220556055142307126912984890431171452173521507180621715976534133436737190377187674798094933460577119501473470122387669540337503454200802611363603905865663617381478278985073508281220973097134177360



for i in range(64):
print(chr(round(flag[i])),end='')

但是看别的师傅的wp,有逆算法直接就解出来了,还有用cv2库的

Pytrans

pyinstxtractor.py 解包

pyc反编译可以看到打开了一个so文件,ida打开这个so文件,有一个check函数,里面有一个方程,z3求解一下得到:511 112 821 949 517 637 897 575 648 738。

在linux里运行一下,一开始的输入就是这10个数,再输一遍,然后说让走迷宫。(比赛时就是这是卡住了)

接下来继续看pyc反编译的代码:

1
2
3
4
decoded_data = base64.b64decode(scrambled_code_string)
uncompressed_data = zlib.decompress(decoded_data)
exec(__import__('marshal').loads(uncompressed_data))

看不太懂,问问gpt:

1
2
3
4
5
6
7
这段代码是Python的代码,它的作用是将经过base64编码和zlib压缩的Python代码字符串解码并执行。

具体来说,代码首先使用Python内置的base64模块对经过编码的字符串进行解码,得到被编码的二进制数据。然后,它使用zlib模块对二进制数据进行解压缩,得到未压缩的二进制数据。最后,代码使用marshal模块将未压缩的二进制数据转换为可执行的Python代码对象,并使用exec()函数将其执行。

需要注意的是,这段代码的来源不明,它可能包含有害代码或安全漏洞,因此不应该随意运行。如果您不确定代码的来源和用途,请谨慎处理。


既然能执行,那看看uncompressed_data里面是什么东西

打印出来后,放入010,是一个缺了文件头的pyc,补上之后反编译:

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
footprint = '3qzqns4hj6\neeaxc!4a-%\nd735_@4l6g\nf1gd1v7hdm\n1+$-953}81\na^21vbnm3!\n-#*f-e1d8_\n2ty9uipok-\n6r1802f7d1\n9wez1c-f{0'
xx0000 = []
footprintlist = footprint.split('\n')
for i in range(len(footprintlist)):
xx0000.append(list(footprintlist[i]))
else:

def xxxx000x0(num):
xx000000 = format(num, '010b')
return xx000000


oxooxxxxxoooo = []
xx0000000 = input("Please enter the previous 10 digits again and ending with '\\n': ").split(' ')
if len(xx0000000) == 10:
try:
for i in xx0000000:
oxooxxxxxoooo.append(int(i))

except:
print('err input!')
exit(-1)

else:
print('err input!')
exit(-1)
for i in range(len(oxooxxxxxoooo)):
oxooxxxxxoooo[i] = list(xxxx000x0(oxooxxxxxoooo[i]))
else:
xx0000x000 = oxooxxxxxoooo
x, o = (0, 0)
xx00x00x0xxx00 = [(x, o)]
xx00x00x0xxx00input = list(input('input maze path:'))
count = 0
while (x, o) != (9, 9):
if count < len(xx00x00x0xxx00input):
xx0000x0xxx00 = xx00x00x0xxx00input[count]
if xx0000x0xxx00 == 'a':
if o > 0 and xx0000x000[x][o - 1] == '0':
o -= 1
count += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
elif xx0000x0xxx00 == 'd':
if o < 9 and xx0000x000[x][o + 1] == '0':
count += 1
o += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
else:
if xx0000x0xxx00 == 'w':
if x > 0 and xx0000x000[x - 1][o] == '0':
count += 1
x -= 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
else:
if xx0000x0xxx00 == 's':
if x < 9 and xx0000x000[x + 1][o] == '0':
count += 1
x += 1
xx00x00x0xxx00.append((x, o))
else:
print('wrong!')
exit(-1)
else:
print('wrong!')
exit(-1)
else:
print('wrong!')
exit(-1)

print('right! you maybe got it,flag is flag{the footprint of the maze path}')

是一个迷宫,迷宫是利用输入的10个数生成的,我们可以修改源码,让他生成完后,自己输出迷宫:

image-20230531130917603

从左上角走到右下角,路径:sddsdssdddwwwddsssssaaaaassddsddwdds

剩下的就简单咯

Emoji Connect

是个小游戏,代码段其实挺复杂的,可以一段段问gpt,大概了解到是一个连连看。

flag处理:

1
2
3
int num = (array[0] - 55296) * 1024 + array[1] - 56320 + 65536 - 128512;
this.number[num] -= (list[1].Row - 1) * (list[1].Column - 1);
this.number[num] -= (list[0].Row - 1) * (list[0].Column - 1);

num数组给出,array数组也有,应该是最后全消了,所以数据都用到了,嫖的脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
array=[]
for i in range(48):
array.append([0]*48)

array[0][0] = "d83dde08";
array[0][1] = "d83dde11";
'''......'''
array[47][46] = "d83dde0f";
array[47][47] = "d83dde25";
number=[25588, 31114, 28727, 26722, 24948, 25135, 25480, 29029, 23025, 25775, 15411, 25423, 25202, 30031, 27380, 30734, 25054, 25109, 20741, 28568, 28802, 24591, 26063, 30940, 30375, 19411, 29573, 20845, 27232, 26743, 25779, 24986, 31498, 30978, 22945, 26563, 35012, 29994, 27016, 29535, 21342, 26573, 27569, 25408, 31567, 25503, 21385, 27207]

for i in range(48):
for j in range(48):
x=int(array[i][j][:4],16)
y=int(array[i][j][4:],16)
num = (x - 55296) * 1024 + y - 56320 + 65536 - 128512
number[num]-=i*j

print(bytes(number))
print(b'flag{'+bytes(number)[6:-6]+b'}')

OldSymbolicCode

是MS-DOS的应用程序,可以使用DOSbox运行,并且可以动调。

逻辑是判断长度是否为36,rc4+tea加密