2021NCTF-Re

NCTF-RE

签到

送IDA又送flag

欢迎来到NCTF-逆向工程(Reverse Engineering)
这里可能有你需要的工具:
ida pro 7.6 :

链接:https://pan.baidu.com/s/1bV2HjBBX0bwwtzORqhErOg

提取码:o49x

Shadowbringer

c++64位程序,ida载入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
std::string::string(v4, "U>F2UsQXN`5sXMELT=:7M_2<X]^1ThaWF0=KM?9IUhAsTM5:T==_Ns&<Vhb!", &v6);
std::allocator<char>::~allocator(&v6);
std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Welcome.Please input your flag:\n");
std::operator>><char>(refptr__ZSt3cin, (std::string *)input);
std::string::string((std::string *)v8, (const std::string *)input);// strcpy
base64encode1((std::string *)v7, (std::string *)v8);// 换表的base64
std::string::operator=((std::string *)input, (const std::string *)v7);// 赋值 第一层密文
std::string::~string((std::string *)v7);
std::string::~string((std::string *)v8);
std::string::string((std::string *)v10, (const std::string *)input);// 复制一个对象v10
base64encode2((std::string *)v9, (std::string *)v10); // base64换表 两次 不同的表
std::string::operator=((std::string *)input, (const std::string *)v9);
std::string::~string((std::string *)v9);
std::string::~string((std::string *)v10);
if ( (unsigned __int8)std::operator==<char>(input, v4) )
std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Right.");
else
std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "Wrong.");
std::string::~string((std::string *)v4);

主要用到了c++ string类来进行处理,结合动调,大致经过了两次base64变表加密,在和v4进行比较。
第一组表,
‘#$%&’,27h,‘()*+,-.s0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[h]’+‘^_`ab’

第二组表
‘ba`_^]h[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210s.-,+*)(’,27h,‘&’‘+’%$#’

两次加密的代码大致相同,主要通过表的长度和每次处理的二进制长度判断为base64.

1
2
3
4
5
6
7
8
9
10
11
std::bitset<8ull>::to_string(v13, v14);     // 转为2进制
for ( j = 0; j < (unsigned __int64)std::string::size((std::string *)&v9); j += 6 )// 6个二进制一组
v7 = (char *)std::string::operator[](&hisoralce, v6);//表索引

while ( (std::string::size(a1) & 3) != 0 )
{
std::operator+<char>(v19, a1, '!');
std::string::operator=(a1, (const std::string *)v19);
std::string::~string((std::string *)v19);
}
//不为4的倍数就不断+!

了解流程后写解密脚本即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import base64
table1='#$%&'+'\x27'+'()*+,-.s0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[h]'+'^_`ab'
table2='ba`_^]h[ZYXWVUTSRQPONMLKJIHGFEDCBA@?>=<;:9876543210s.-,+*)('+'\x27'+'&%$#'
base='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
enc='U>F2UsQXN`5sXMELT=:7M_2<X]^1ThaWF0=KM?9IUhAsTM5:T==_Ns&<Vhb!'
#enc='FsJ7M?b<U->2M>U:'#123456789测试
def newbase(enc,table):
m=''
for i in range(len(enc)):
if enc[i] in table:
m+=base[table.index(enc[i])]
else:
m+='='
print(base64.b64decode(m))
return base64.b64decode(m)
c1=newbase(enc,table2).decode()
newbase(c1,table1)
#NCTF{H0m3_r1d1n9_h0m3_dy1n9_h0p3}

鲨鲨的秘密

32位程序,ida载入

1
2
3
4
5
IpAdress = malloc(0x20u);
VirtualProtect(IpAdress, 0x20u, 0x40u, &flOldProtect);
dword_404E48 = (int)IpAdress;
*(_BYTE *)IpAdress = 0xC3; // ret的机器码
((void (*)(void))IpAdress)

刚载入就有种莫名其妙的熟悉感,和西湖论剑的一道逆向题思路差不多,又是体力活。
是一种修改代码的操作数并单语句执行的SMC,通过一个数组来确定赋值代码长度的大小,和选定相应的操作数和修改的位置。

挖出汇编代码,结合动调分析语句还原算法。

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
mov     ds:dword_403474, 0FFFFFFFFh            // mov output ,0xffffffff
mov ecx, ds:dword_403464 // mov ecx,index(0)
mov dl, byte ptr ds:VirtualProtect[ecx] // mov dl,input[0]
mov byte ptr ds:dword_403470, dl // mov temp,dl
movzx eax, byte ptr ds:dword_403470 // mov eax, temp 输入传给eax
xor eax, ds:dword_403474 // xor eax,output 取反类似
mov byte ptr ds:dword_403470, al // mov temp , al 保存取反的值
movzx ecx, byte ptr ds:dword_403470 // mov ecx,temp
and ecx, 0FFh // and ecx,0xff
mov byte ptr ds:dword_403470, cl // mov temp,cl
mov edx, ds:dword_403474 // mov edx,output
shr edx, 8 // shr edx,8
mov ds:dword_403474, edx // mov output,edx
movzx eax, byte ptr ds:dword_403470 // mov eax,temp
mov ecx, ds:dword_403474 // mov ecx,output
xor ecx, dword ptr ds:byte_403058[eax*4] // xor ecx, sbox[4*eax] //174841BC xor sbox[4*0x9e] 结果保存到output
mov ds:dword_403474, ecx
mov edx, ds:dword_403464 ....
mov al, [edx+403005h]
mov byte ptr ds:dword_403470, al
movzx ecx, byte ptr ds:dword_403470
xor ecx, ds:dword_403474
mov byte ptr ds:dword_403470, cl
mov edx, ds:dword_403474
shr edx, 8
mov ds:dword_403474, edx
movzx eax, byte ptr ds:dword_403470
mov ecx, ds:dword_403474
xor ecx, dword ptr ds:byte_403058[eax*4] //xor ecx,sbox[4*eax] //eax 0xdd
mov ds:dword_403474, ecx //mov output,ecx
mov edx, ds:dword_403474 //mov edx,output
xor edx, 0FFFFFFFFh //xor edx, 0FFFFFFFFh
mov ds:dword_403474, edx //mov output edx

python代码如下

1
2
3
4
5
6
7
8
9
10
11
12
input='a'*40
output=0xffffffff
for index in range(0,40,2):
tmp=(ord(input[index])^output)&0xff
output=output>>8
output=output^somebox[tmp]
#print("%x %x"%(tmp,output))
tmp = (ord(input[index+1]) ^ output) & 0xff
output = output >> 8
output = output ^ somebox[tmp]
output=output^0xffffffff
print("%x %x" % (tmp, output))

可知是两个字节为一组进行的处理,z3解因为涉及下标问题不好下手,z3所得中间方程REF的参数不能转换为其他类型的变量,所以直接爆破。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
somebox=[0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D]
enc=[0xC0F6605E, 0x00B16E0A, 0x3319A2D2, 0x57CAB7B7, 0x9A646D9C, 0xBDD82726, 0xD838FB91, 0x8DE10BB3, 0x176B0DAD, 0x685FDEEF, 0x2C1FF7B1, 0x6C444296, 0xA15CFE90, 0x20CD8721, 0x62967CE8, 0x2C1641FD, 0x572D0F9A, 0xAE52DC2C, 0x50497DCF, 0xFF6ABF4A]
s=''
enc=[0xC0F6605E, 0x00B16E0A, 0x3319A2D2, 0x57CAB7B7, 0x9A646D9C, 0xBDD82726, 0xD838FB91, 0x8DE10BB3, 0x176B0DAD, 0x685FDEEF, 0x2C1FF7B1, 0x6C444296, 0xA15CFE90, 0x20CD8721, 0x62967CE8, 0x2C1641FD, 0x572D0F9A, 0xAE52DC2C, 0x50497DCF, 0xFF6ABF4A]
for i in range(20):
for m in range(32,128):
for n in range(32,128):
output = 0xffffffff
tmp=(m^output)&0xff
output=output>>8
output=output^somebox[tmp]
#print("%x %x"%(tmp,output))
tmp = (n ^ output) & 0xff
output = output >> 8
output = output ^ somebox[tmp]
output=output^0xffffffff
if output==enc[i]:
s+=chr(m)+chr(n)

print(s)
#NCTF{rLdE57TG0iHA39qUnFZp6LeJyYEBcxMNL7}

狗狗的秘密

挺不错的,解完想暴打出题人。
32位程序,ida载入获得假flag一枚

不过main之前有个TlsCallback函数,直接下个断点,动态分析。

1
2
3
4
5
6
7
8
9
10
11
12
if ( !v9 && !IsDebuggerPresent() )
{
off_825014 = (int (__cdecl *)(_DWORD))sub_823000;
v8 = (unsigned int *)((char *)sub_823000 + 256);
for ( i = 0; i < 24; ++i )
v8 += 2;
for ( j = 0; j < 24; ++j )
{
v8 -= 2;
sub_8211F0(v8);
}
}

反调试,off_825014在主函数出现过,但是个假逻辑,所以这部分内容是SMC修改技术。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
unsigned int __cdecl sub_8211F0(unsigned int *a1)
{
unsigned int result; // eax
int i; // [esp+0h] [ebp-Ch]
unsigned int v3; // [esp+4h] [ebp-8h]
unsigned int v4; // [esp+8h] [ebp-4h]

v4 = *a1;
v3 = a1[1];
for ( i = 0; i < 64; ++i )
{
v3 -= (dword_825004[(*(_DWORD *)delta >> 11) & 3] + *(_DWORD *)delta) ^ (v4 + ((v4 >> 5) ^ (16 * v4)));
*(_DWORD *)delta += dword_825000;
v4 -= (dword_825004[delta[0] & 3] + *(_DWORD *)delta) ^ (v3 + ((v3 >> 5) ^ (16 * v3)));
}
*a1 = v4;
result = v3;
a1[1] = v3;
return result;
}

直接改eip绕过这个反调试即可,同时修改代码用的xTea,不过delta的值有个小坑,main函数中有个创建线程的函数,将delta赋值为0xDA76C600,patch进行修改,后面下个断F9。

线程的执行顺序不是太清楚,不过TLSCALLBACK在main之前执行,而delta在main函数中被改掉,为什么会应用到smc中呢,有待解决。

修复函数后拿到真正处理逻辑。

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
int __cdecl sub_823000(const char *a1)
{
signed int v2; // [esp+0h] [ebp-98h]
unsigned int v3; // [esp+10h] [ebp-88h]
signed int v4; // [esp+1Ch] [ebp-7Ch]
int v5; // [esp+2Ch] [ebp-6Ch]
int v6; // [esp+2Ch] [ebp-6Ch]
char v7; // [esp+32h] [ebp-66h]
signed int Size; // [esp+34h] [ebp-64h]
unsigned int v9; // [esp+38h] [ebp-60h]
int k; // [esp+38h] [ebp-60h]
unsigned __int8 *v11; // [esp+3Ch] [ebp-5Ch]
int i; // [esp+40h] [ebp-58h]
signed int j; // [esp+40h] [ebp-58h]
signed int m; // [esp+40h] [ebp-58h]
signed int n; // [esp+40h] [ebp-58h]
signed int ii; // [esp+40h] [ebp-58h]
char v17[62]; // [esp+44h] [ebp-54h]
int v18; // [esp+82h] [ebp-16h]
int v19; // [esp+86h] [ebp-12h]
int v20; // [esp+8Ah] [ebp-Eh]
int v21; // [esp+8Eh] [ebp-Ah]
__int16 v22; // [esp+92h] [ebp-6h]

v3 = strlen(a1);
Size = 146 * v3 / 0x64 + 1;
v4 = 0;
v11 = (unsigned __int8 *)malloc(Size);
v17[0] = 82;
v17[1] = -61;
v17[2] = 26;
v17[3] = -32;
v17[4] = 22;
v17[5] = 93;
v17[6] = 94;
v17[7] = -30;
v17[8] = 103;
v17[9] = 31;
v17[10] = 31;
v17[11] = 6;
v17[12] = 6;
v17[13] = 31;
v17[14] = 23;
v17[15] = 6;
v17[16] = 15;
v17[17] = -7;
v17[18] = 6;
v17[19] = 103;
v17[20] = 88;
v17[21] = -78;
v17[22] = -30;
v17[23] = -116;
v17[24] = 15;
v17[25] = 42;
v17[26] = 6;
v17[27] = -119;
v17[28] = -49;
v17[29] = 42;
v17[30] = 6;
v17[31] = 31;
v17[32] = -104;
v17[33] = 26;
v17[34] = 62;
v17[35] = 23;
v17[36] = 103;
v17[37] = 31;
v17[38] = -9;
v17[39] = 58;
v17[40] = 68;
v17[41] = -61;
v17[42] = 22;
v17[43] = 51;
v17[44] = 105;
v17[45] = 26;
v17[46] = 117;
v17[47] = 22;
v17[48] = 62;
v17[49] = 23;
v17[50] = -43;
v17[51] = 105;
v17[52] = 122;
v17[53] = 27;
v17[54] = 68;
v17[55] = 68;
v17[56] = 62;
v17[57] = 103;
v17[58] = -9;
v17[59] = -119;
v17[60] = 103;
v17[61] = -61;
v18 = 0;
v19 = 0;
v20 = 0;
v21 = 0;
v22 = 0;
memset(v11, 0, Size);
v9 = 0;
for ( i = 0; i < 256; ++i )
{
v7 = byte_825018[i];
byte_825018[i] = byte_825018[(i + *((unsigned __int8 *)&delta + i % 4)) % 256];// delta变为0了
byte_825018[(i + *((unsigned __int8 *)&delta + i % 4)) % 256] = v7;
}
while ( v9 < strlen(a1) )
{
v5 = a1[v9];
for ( j = 146 * v3 / 0x64; ; --j )
{
v6 = v5 + (v11[j] << 8);
v11[j] = v6 % 47;
v5 = v6 / 47;
if ( j < v4 )
v4 = j;
if ( !v5 && j <= v4 )
break;
}
++v9;
}
for ( k = 0; !v11[k]; ++k )
;
for ( m = 0; m < Size; ++m )
v11[m] = byte_825118[v11[k++]]; // 单表替换
while ( m < Size )
v11[m++] = 0;
v2 = strlen((const char *)v11);
for ( n = 0; n < v2; ++n )
v11[n] ^= byte_825018[v11[n]]; // 异或处理
for ( ii = 0; ii < v2; ++ii )
{
if ( v11[ii] != (unsigned __int8)v17[ii] )
{
printf("Wrong!\n", v2);
exit(0);
}
}
printf("Right!\n", v2);
return 0;
}

delta的值是0,需要注意一下,接着就是写脚本逆向,z3不好直接求解,加密流程是先将输入转为47进制下每位的值存在数组v11中,找到第一个非0值的下标k,接着进行单表替换和异或。

又是一个z3直接出,却被ban了的题,类型转换有点坑

因为涉及到表索引和本身异或不好逆向还原,所以想着先爆破v11数组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
enc=[0x52, 0xC3, 0x1A, 0xE0, 0x16, 0x5D, 0x5E, 0xE2, 0x67, 0x1F, 0x1F, 0x06, 0x06, 0x1F, 0x17, 0x06, 0x0F, 0xF9, 0x06, 0x67, 0x58, 0xB2, 0xE2, 0x8C, 0x0F, 0x2A, 0x06, 0x89, 0xCF, 0x2A, 0x06, 0x1F, 0x98, 0x1A, 0x3E, 0x17, 0x67, 0x1F, 0xF7, 0x3A, 0x44, 0xC3, 0x16, 0x33, 0x69, 0x1A, 0x75, 0x16, 0x3E, 0x17, 0xD5, 0x69, 0x7A, 0x1B, 0x44, 0x44, 0x3E, 0x67, 0xF7, 0x89, 0x67, 0xC3]
c=[]
for i in range(61):
temp=[]
for j in range(47):
tmp=tb2[j]
tmp=tmp^table[tmp]
if tmp==enc[i]:
temp.append(j)
if len(temp)==1:
c.append(temp[0])
else:
c.append(temp)
c.insert(0,0)

#[0, 2, 0, [33, 45], 44, 30, 40, 8, 23, [7, 11, 22], [34, 37], [34, 37], [19, 20, 43], [19, 20, 43], [34, 37], 24, [19, 20, 43], [4, 31], 29, [19, 20, 43], [7, 11, 22], 13, 5, 23, 41, [4, 31], 35, [19, 20, 43], 9, 14, 35, [19, 20, 43], [34, 37], 3, [33, 45], 10, 24, [7, 11, 22], [34, 37], 38, 1, 25, 0, 30, 6, 42, [33, 45], 36, 30, 10, 24, 21, 42, 26, 28, 25, 25, 10, [7, 11, 22], 38, 9, [7, 11, 22]]

v11第一位是0,根据加密的最后一位是0xc3,或者多次测试都可知,不过这解有点多,下面就是对c进行排列组合,之后47进制转,long_to_bytes下即可,不过这…tmd,dfs不太会写,直接硬爆破了,大概跑了半小时,直接整emo了。

跑起来才意识到从高位开始爆破会比较快,高位对转字符的影响较大,傻了

完整如下

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


def dododo(c):
sum = 0
for i in range(62):
sum += c[i] * pow(47, 61 - i)
m=long_to_bytes(sum)
try:
flag=m.decode()
print(flag)
exit(0)
except:
pass


enc=[0x52, 0xC3, 0x1A, 0xE0, 0x16, 0x5D, 0x5E, 0xE2, 0x67, 0x1F, 0x1F, 0x06, 0x06, 0x1F, 0x17, 0x06, 0x0F, 0xF9, 0x06, 0x67, 0x58, 0xB2, 0xE2, 0x8C, 0x0F, 0x2A, 0x06, 0x89, 0xCF, 0x2A, 0x06, 0x1F, 0x98, 0x1A, 0x3E, 0x17, 0x67, 0x1F, 0xF7, 0x3A, 0x44, 0xC3, 0x16, 0x33, 0x69, 0x1A, 0x75, 0x16, 0x3E, 0x17, 0xD5, 0x69, 0x7A, 0x1B, 0x44, 0x44, 0x3E, 0x67, 0xF7, 0x89, 0x67, 0xC3]
table=[0x21, 0x43, 0x65, 0x87, 0x09, 0x21, 0x43, 0x65, 0xA2, 0x9B, 0xF4, 0xDF, 0xAC, 0x7C, 0xA1, 0xC6, 0x16, 0xD0, 0x0F, 0xDD, 0xDC, 0x73, 0xC5, 0x6B, 0xD1, 0x96, 0x47, 0xC2, 0x26, 0x67, 0x4E, 0x41, 0x82, 0x20, 0x56, 0x9A, 0x6E, 0x33, 0x92, 0x88, 0x29, 0xB5, 0xB4, 0x71, 0xA9, 0xCE, 0xC3, 0x34, 0x50, 0x59, 0xBF, 0x2D, 0x57, 0x22, 0xA6, 0x30, 0x04, 0xB2, 0xCD, 0x36, 0xD5, 0x68, 0x4D, 0x5B, 0x45, 0x9E, 0x85, 0xCF, 0x9D, 0xCC, 0x61, 0x78, 0x32, 0x76, 0x31, 0xE3, 0x80, 0xAD, 0x39, 0x4F, 0xFA, 0x72, 0x83, 0x4C, 0x86, 0x60, 0xB7, 0xD7, 0x63, 0x0C, 0x44, 0x35, 0xB3, 0x7B, 0x19, 0xD4, 0x69, 0x08, 0x0B, 0x1F, 0x3D, 0x11, 0x79, 0xD3, 0xEE, 0x93, 0x42, 0xDE, 0x23, 0x3B, 0x5D, 0x8D, 0xA5, 0x77, 0x5F, 0x58, 0xDB, 0x97, 0xF6, 0x7A, 0x18, 0x52, 0x15, 0x74, 0x25, 0x62, 0x2C, 0x05, 0xE8, 0x0D, 0x98, 0x2A, 0x43, 0xE2, 0xEF, 0x48, 0x87, 0x49, 0x1C, 0xCA, 0x2B, 0xA7, 0x8A, 0x09, 0x81, 0xE7, 0x53, 0xAA, 0xFF, 0x6F, 0x8E, 0x91, 0xF1, 0xF0, 0xA4, 0x46, 0x3A, 0x7D, 0x54, 0xEB, 0x2F, 0xC1, 0xC0, 0x0E, 0xBD, 0xE1, 0x6C, 0x64, 0xBE, 0xE4, 0x02, 0x3C, 0x5A, 0xA8, 0x9F, 0x37, 0xAF, 0xA0, 0x13, 0xED, 0x1B, 0xEC, 0x8B, 0x3E, 0x7E, 0x27, 0x99, 0x75, 0xAB, 0xFE, 0xD9, 0x3F, 0xF3, 0xEA, 0x70, 0xF7, 0x95, 0xBA, 0x1D, 0x40, 0xB0, 0xF9, 0xE5, 0xF8, 0x06, 0xBC, 0xB6, 0x03, 0xC9, 0x10, 0x9C, 0x2E, 0x89, 0x5C, 0x7F, 0xB1, 0x1A, 0xD6, 0x90, 0xAE, 0xDA, 0xE6, 0x5E, 0xB9, 0x84, 0xE9, 0x55, 0xBB, 0xC7, 0x0A, 0xE0, 0x66, 0xF2, 0xD8, 0xCB, 0x00, 0x12, 0xB8, 0x17, 0x94, 0x6A, 0x4A, 0x01, 0x24, 0x14, 0x51, 0x07, 0x65, 0x21, 0xC8, 0x38, 0xFD, 0x8F, 0xC4, 0xF5, 0xFC]
#delta=[0,0xc6,0x76,0xda]
tb2=[0xA7, 0x1C, 0x7E, 0xAF, 0xD9, 0xC2, 0xC0, 0xBE, 0x1F, 0x45, 0x9A, 0x85, 0x26, 0xE3, 0x87, 0xC3, 0x21, 0xE0, 0x95, 0x10, 0x71, 0x70, 0x02, 0x75, 0x35, 0xA5, 0x1D, 0x0D, 0x2F, 0xEE, 0x25, 0x7B, 0xB5, 0x82, 0x66, 0x8D, 0xDB, 0x53, 0x3A, 0x29, 0xD4, 0x43, 0x99, 0x97, 0x9D, 0xE8, 0x49, 0x00]

c=[]

for i in range(61):
temp=[]
for j in range(47):
tmp=tb2[j]
tmp=tmp^table[tmp]
if tmp==enc[i]:
temp.append(j)
if len(temp)==1:
c.append(temp[0])
else:
c.append(temp)
c.insert(0,0)
print(c)
for i in c:
if isinstance(i,int):
pass
else:
print(i)
c[3]=45
tblen=[]
l=1
index=[]
for i in range(len(c)):
try:
tblen.append(len(c[i]))
l*=len(c[i])
index.append(i)
except:
tblen.append(1)

print(tblen)
print(index)

sum=0
t1=[7, 11, 22]
t2=[34, 37]
t3=[19, 20, 43]
t4=[4, 31]
t5=[33, 45]


for a1 in range(3):
c[9]=t1[a1]
for a2 in range(2):
c[10]=t2[a2]
for a3 in range(2):
c[11]=t2[a3]
for a4 in range(3):
c[12]=t3[a4]
for a5 in range(3):
c[13]=t3[a5]
for a6 in range(2):
c[14]=t2[a6]
for a7 in range(3):
c[16]=t3[a7]
for a8 in range(2):
c[17]=t4[a8]
for a9 in range(3):
c[19]=t3[a9]
for a10 in range(3):
c[20]=t1[a10]
for a11 in range(2):
c[25]=t4[a11]
for a12 in range(3):
c[27]=t3[a12]
for a13 in range(3):
c[31]=t3[a13]
for a14 in range(2):
c[32]=t2[a14]
for a15 in range(2):
c[34]=t5[a15]
for a16 in range(3):
c[37]=t1[a16]
for a17 in range(2):
c[38]=t2[a17]
for a18 in range(2):
c[46]=t5[a18]
for a19 in range(3):
c[58]=t1[a19]
for a20 in range(3):
c[61]=t1[a20]
dododo(c)

#NCTF{ADF0E239-D911-3781-7E40-A575A19E5835}

题感觉都挺好玩的,就是把z3 ban掉太不够意思了,自己的算法能力不是太给力。


总结:C++或者再复杂一点的语言还得是动调,线程的调用关系要梳理清晰还有常见算法,同时巩固了一下西湖的SMC思路。

NCTF还是差一道Android就能AK了,native层的代码看的头皮发麻,有时间要及时复现和反思,另:航哥TQQQLLL,直接给秒了

加上安洵杯,上周小比赛还是蛮多的,能学到很多东西,但还没完全复现。最近临近考试周,实验和考试比较多,要去冲刺了,估计是最近两周不会再摸了。

别贪心,我们不会什么都有,别灰心,我们也不会什么都没有。让我们像个英勇的蒙古骑士一样,拿起手中锋利的马刀,去与更强大的敌人拼杀吧!


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!