桂电2019 re write up

re

checksec 一下发现加了upx壳,upx -d 脱壳

IDA f5发现

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
_BOOL8 __fastcall sub_4009AE(char *a1)
{
if ( 1629056 * *a1 != 166163712 )
return 0LL;
if ( 6771600 * a1[1] != 731332800 )
return 0LL;
if ( 3682944 * a1[2] != 357245568 )
return 0LL;
if ( 10431000 * a1[3] != 1074393000 )
return 0LL;
if ( 3977328 * a1[4] != 489211344 )
return 0LL;
if ( 5138336 * a1[5] != 518971936 )
return 0LL;
if ( 7532250 * a1[7] != 406741500 )
return 0LL;
if ( 5551632 * a1[8] != 294236496 )
return 0LL;
if ( 3409728 * a1[9] != 177305856 )
return 0LL;
if ( 13013670 * a1[10] != 650683500 )
return 0LL;
if ( 6088797 * a1[11] != 298351053 )
return 0LL;
if ( 7884663 * a1[12] != 386348487 )
return 0LL;
if ( 8944053 * a1[13] != 438258597 )
return 0LL;
if ( 5198490 * a1[14] != 249527520 )
return 0LL;
if ( 4544518 * a1[15] != 445362764 )
return 0LL;
if ( 3645600 * a1[17] != 174988800 )
return 0LL;
if ( 10115280 * a1[16] != 981182160 )
return 0LL;
if ( 9667504 * a1[18] != 493042704 )
return 0LL;
if ( 5364450 * a1[19] != 257493600 )
return 0LL;
if ( 13464540 * a1[20] != 767478780 )
return 0LL;
if ( 5488432 * a1[21] != 312840624 )
return 0LL;
if ( 14479500 * a1[22] != 1404511500 )
return 0LL;
if ( 6451830 * a1[23] != 316139670 )
return 0LL;
if ( 6252576 * a1[24] != 619005024 )
return 0LL;
if ( 7763364 * a1[25] != 372641472 )
return 0LL;
if ( 7327320 * a1[26] != 373693320 )
return 0LL;
if ( 8741520 * a1[27] != 498266640 )
return 0LL;
if ( 8871876 * a1[28] != 452465676 )
return 0LL;
if ( 4086720 * a1[29] != 208422720 )
return 0LL;
if ( 9374400 * a1[30] == 515592000 )
return 5759124 * a1[31] == 719890500;
return 0LL;
}

只能说,出题人真无聊,不过也挺有耐心的,直接跑脚本

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 <iostream>
using namespace std;
int main()
{
string flag = "********************************";
flag[0] = (char)(166163712 / 1629056 );
flag[1] = (char)(731332800 / 6771600 );
flag[2] = (char)(357245568 / 3682944 );
flag[3] = (char)(1074393000 / 10431000 );
flag[4] = (char)(489211344 / 3977328 );
flag[5] = (char)(518971936 / 5138336 );
flag[6+1] = (char)(406741500 / 7532250 );
flag[7+1] = (char)(294236496 / 5551632 );
flag[8+1] = (char)(177305856 / 3409728 );
flag[9+1] = (char)(650683500 / 13013670 );
flag[10+1] = (char)(298351053 / 6088797 );
flag[11+1] = (char)(386348487 / 7884663 );
flag[12+1] = (char)(438258597 / 8944053 );
flag[13+1] = (char)(249527520 / 5198490 );
flag[14+1] = (char)(445362764 / 4544518 );
flag[16+1] = (char)(174988800 / 3645600 );
flag[15+1] = (char)(981182160 / 10115280 );
flag[17+1] = (char)(493042704 / 9667504 );
flag[18+1] = (char)(257493600 / 5364450 );
flag[19+1] = (char)(767478780 / 13464540 );
flag[20+1] = (char)(312840624 / 5488432 );
flag[21+1] = (char)(1404511500 / 14479500 );
flag[22+1] = (char)(316139670 / 6451830 );
flag[23+1] = (char)(619005024 / 6252576 );
flag[24+1] = (char)(372641472 / 7763364 );
flag[25+1] = (char)(373693320 / 7327320 );
flag[26+1] = (char)(498266640 / 8741520 );
flag[27+1] = (char)(452465676 / 8871876 );
flag[28+1] = (char)(208422720 / 4086720 );
flag[29+1] = (char)(515592000 / 9374400 );
flag[30+1] = (char)(719890500 / 5759124 );
cout<<flag<<endl;

return 0;
}

encrypt

主要对输入字符串 s 执行两次操作,第一次是异或

由于我在IDA并没有找到v9的值 ,所以从gdb上一个一个记录下来了,但是其实后来发现v9是由sub_4006b6得来的,但是懒得去逆这个函数了(反正数据我已经拿到了)

1
data = [0x10,0x59,0x9c,0x92,0x6,0x22,0xcf,0xa5,0x72,0x1e,0x45,0x6a,0x6,0xcb,0x8,0xc3,0xe4,0x49,0x5a,0x63,0xc,0xdf,0xf6,0x5f,0x8,0x28,0xbd,0xe2,0x10,0x15,0x1f,0x6e,0xaa,0x5a,0xca,0xec,0x80,0xaf,0x9b,0x16,0xbb,0x3d,0x13,0x2f,0x6a,0xa4,0xc7,0x2e,0xbc,0x4b,0x60,0x9a]

异或后到了一个base64加密的位置,一开始我以为是base64加密,但是第一:没有表,第二:加了61,所以其实就是拿了base64移位的操作得到下标(0~64)然后+61变成可见字符 ,再跟’Z`TzzTrD|fQP[_VVL|yneURyUmFklVJgLasJroZpHRxIUlH\vZE=’对应

所以,思路就很清晰了

1、这串字符串-61得到base64的下标,对应上base64表得到base64加密结果,再解密回去

2、异或data得到flag

number_game

这道 题还算挺有意思 的,搞到最后是一个数独

先检测输入,只能是[0,1,2,3,4]

这里用递归将输入放在了堆块中,为后面的乱序做准备

这里打乱输入顺序写入a2,其实就是递归查找,当下一个(+8)没有时,就写入,所以顺序就是7381940526

继续往下,就是填数独了,填完检测,

1
2
3
4
5
1 4 # 2 3
3 0 # 1 #
0 # 2 3 #
# 3 # # 0
4 2 # # 1
1
2
3
4
5
1 4 0 2 3
3 0 4 1 2
0 1 2 3 4
2 3 1 4 0
4 2 3 0 1

所以填入的数据 是0421421430,根据打乱的顺序排回去得到1134240024

0%