我太菜了,呜呜呜
这个说要用正确的解密软件解密,我还想了好久,想不到有啥解密软件,直接IDA
先查壳
找到主函数,分析代码逻辑
// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
char str12581[59]; // [rsp+20h] [rbp-60h] BYREF
char flag[32]; // [rsp+60h] [rbp-20h] BYREF
char str[27]; // [rsp+80h] [rbp+0h] BYREF
int j; // [rsp+A0h] [rbp+20h]
int index; // [rsp+A4h] [rbp+24h]
char *encryption; // [rsp+A8h] [rbp+28h]
_BYTE len[12]; // [rsp+B4h] [rbp+34h] OVERLAPPED
int n; // [rsp+C4h] [rbp+44h]
int n1; // [rsp+C8h] [rbp+48h]
int j_1; // [rsp+CCh] [rbp+4Ch]
int j_0; // [rsp+D0h] [rbp+50h]
int carry; // [rsp+D4h] [rbp+54h]
int high; // [rsp+D8h] [rbp+58h]
int i; // [rsp+DCh] [rbp+5Ch]
_main();
n1 = 18;
strcpy(str, "ERaQux2kCQGLeLwddrgMCKtL6x"); // flag最终的变化形式
scanf("%s", flag);
n = strlen(flag);
if ( n <= 32 ) // flag长度小于32
{
*(_QWORD *)&len[4] = 0i64;
*(_QWORD *)len = (unsigned int)(138 * strlen(flag) / 0x64) + 1;// len=36
strcpy(str12581, "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
encryption = (char *)malloc(*(int *)len);
index = 0;
memset(encryption, 0, *(int *)len);
high = *(_DWORD *)len - 1; // high=35
j = 0;
i = 0;
while ( i < strlen(flag) )
{
carry = flag[i];
for ( j_0 = *(_DWORD *)len - 1; j_0 > high || carry; --j_0 )
{
carry += encryption[j_0] << 8;
encryption[j_0] = (char)carry % 58;
carry /= 58;
if ( !j_0 )
break;
}
++i;
high = j;
}
for ( i = 0; !encryption[i]; ++i )
;
j_1 = 0;
while ( *(int *)len > i )
{
if ( str[j_1] != str12581[encryption[i]] )
{
printf("Wrong answer!");
system("pause");
return 0;
}
++i;
++j_1;
}
printf("Your input is the right answer!");
system("pause");
return 0;
}
else
{
printf("Wrong answer!");
system("pause");
return 0;
}
}
主要就是这一段的加密方式,我乍一眼也没看明白,然后跑了下这个加密方式
while ( i < strlen(flag) )
{
carry = flag[i];
for ( j_0 = *(_DWORD *)len - 1; j_0 > high || carry; --j_0 )
{
carry += encryption[j_0] << 8;
encryption[j_0] = (char)carry % 58;
carry /= 58;
if ( !j_0 )
break;
}
++i;
high = j;
}
随便整个字符串试一下
char flag[] = "ISCC{hello_word}";
int carry;
int j_0,i=0,j=0,high=22,len=23,k;
char en[24]={0};
while(i < strlen(flag))
{
carry = flag[i];
for(j_0 = 22; j_0 > high || carry ; --j_0)
{
//printf("carry = %d\n",carry);
carry += en[j_0] << 8;
en[j_0] = carry % 58;
carry /= 58;
if(!j_0) break;
}
printf("i = %d\n",i);
for(k = 0 ; k < 23;k++)
{
printf("%d ",en[k]);
}
++i;
high=j;
}
运行结果:
这样就好看多了,可以看出都是从最后一位开始加密,每轮加密都会比上面的多两个数,第一个数是carry除以58的商,第二个数是carry除以58的余数,根据这个可以算出上一个carry,以及上一轮的最后一轮的第一个数。
根据这个可以写出脚本
Str = "ERaQux2kCQGLeLwddrgMCKtL6x"
Str_1 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
en = []
for i in range(len(Str)):
en.append(Str_1.find(Str[i]))
print(en)
def f(list):
last_list = []
carry = 0
for i in range(0,len(list)):
carry *= 58
carry += list[i]
t = carry // 256
last_list.append( t)
carry -= (t * 256)
del last_list[0] #删除掉开始的零元素
print(last_list)
return carry,last_list
flag = [0] * 26
for i in range(25,-1,-1):
flag[i],en = f(en)
for i in flag:
if i > 0:
print(chr(i),end="")
print(flag)
运行结果
[13, 24, 33, 23, 52, 55, 1, 43, 11, 23, 15, 19, 37, 19, 54, 36, 36, 49, 39, 20, 11, 18, 51,
19, 5, 55]
[3, 2, 22, 56, 36, 0, 39, 47, 22, 56, 27, 28, 27, 2, 14, 37, 17, 23, 54, 39, 27, 2, 0, 43, 43]
[0, 39, 55, 55, 24, 27, 19, 51, 56, 23, 38, 49, 28, 45, 21, 25, 38, 48, 27, 19, 47, 20, 49,
6]
[0, 9, 3, 9, 22, 17, 56, 35, 45, 49, 44, 34, 45, 2, 7, 7, 10, 9, 9, 47, 31, 6, 57]
[0, 2, 2, 56, 55, 20, 22, 19, 51, 36, 11, 26, 52, 46, 14, 17, 28, 7, 29, 50, 11, 7]
[0, 0, 26, 55, 28, 49, 27, 41, 38, 24, 56, 3, 48, 12, 16, 48, 21, 18, 53, 25, 24]
[0, 0, 6, 6, 13, 19, 21, 13, 30, 0, 12, 40, 43, 5, 29, 10, 55, 33, 42, 53]
[0, 0, 1, 22, 14, 46, 30, 37, 2, 41, 42, 43, 38, 44, 17, 2, 1, 41, 36]
[0, 0, 0, 18, 10, 35, 0, 34, 39, 7, 37, 18, 55, 26, 20, 9, 56, 33]
[0, 0, 0, 4, 6, 54, 8, 43, 11, 33, 52, 23, 45, 10, 55, 18, 33]
[0, 0, 0, 0, 54, 7, 42, 44, 13, 2, 40, 24, 24, 16, 30, 38]
[0, 0, 0, 0, 12, 15, 20, 6, 22, 51, 47, 12, 45, 21, 50]
[0, 0, 0, 0, 2, 45, 9, 31, 20, 34, 22, 54, 5, 43]
[0, 0, 0, 0, 0, 36, 29, 46, 30, 28, 36, 53, 2]
[0, 0, 0, 0, 0, 8, 15, 47, 14, 9, 11, 57]
[0, 0, 0, 0, 0, 1, 50, 41, 3, 38, 19]
[0, 0, 0, 0, 0, 0, 24, 36, 28, 27]
[0, 0, 0, 0, 0, 0, 5, 33, 37]
[0, 0, 0, 0, 0, 0, 1, 15]
[0, 0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0, 0]
[0, 0, 0, 0, 0]
[0, 0, 0, 0]
[0, 0, 0]
[0, 0]
[0]
[]
ISCC{T5xr15ruVEyXI}[0, 0, 0, 0, 0, 0, 0, 73, 83, 67, 67, 123, 84, 53, 120, 114, 49, 53, 114, 117, 86, 69, 121, 88, 73, 125]
得到flag: ISCC{T5xr15ruVEyXI}
这题0解,还是等着看别人的wp吧
还是先查看信息
IDA查看字符串,直接定位到关键函数
代码很简单,就一个异或和一个加法
写个脚本出来就行
#include
#include
#include
int main()
{
int v9[20] = {0};
char v6[21] = "LWHFUENGDJGEFHYDHIGJ";
char flag[21];
int i,j,k;
v9[0] = 149;
v9[1] = 169;
v9[2] = 137;
v9[3] = 134;
v9[4] = 212;
v9[5] = 188;
v9[6] = 177;
v9[7] = 184;
v9[8] = 177;
v9[9] = 197;
v9[10] = 192;
v9[11] = 179;
v9[12] = 153;
v9[13] = 142;
v9[14] = 191;
v9[15] = 130;
v9[16] = 167;
v9[17] = 191;
v9[18] = 104;
v9[19] = 184;
for (i = 0 ; i < 20 ; i ++)
{
flag[i] = v9[i] - v6[i];
flag[i] ^= i;
printf("%c",flag[i]);
}
return 0;
}
运行结果:
还是先查下壳
查看字符串,然后定位到主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
void *v3; // rsp
int v2[32]; // [rsp+20h] [rbp-60h] BYREF
int k[4]; // [rsp+A0h] [rbp+20h] BYREF
char v[32]; // [rsp+B0h] [rbp+30h] BYREF
int n; // [rsp+DCh] [rbp+5Ch]
int (*p_v1)[]; // [rsp+E0h] [rbp+60h]
__int64 v10; // [rsp+E8h] [rbp+68h]
int n1; // [rsp+F4h] [rbp+74h]
int i; // [rsp+F8h] [rbp+78h]
int i_0; // [rsp+FCh] [rbp+7Ch]
_main();
n1 = 18;
v10 = 17i64;
v3 = alloca(80i64);
p_v1 = (int (*)[])v2;
v2[0] = 0x8D7FFB13;
v2[1] = 0x8B2B6DB0;
v2[2] = 0x66C4403F;
v2[3] = 0x7413DD82;
v2[4] = 0xDBF303FC;
v2[5] = 0x417C54F3;
v2[6] = 0x428681FC;
v2[7] = 0xDE6B433E;
v2[8] = 0x88CD333A;
v2[9] = 156067879;
v2[10] = 1935606960;
v2[11] = 0x96FAB237;
v2[12] = 0xF5ED4CB2;
v2[13] = 3273616493;
v2[14] = 2496521664;
v2[15] = 1139822545;
v2[16] = 3741141319;
v2[17] = 244541121;
k[0] = 'I';
k[1] = 'S';
k[2] = 'C';
k[3] = 'C';
scanf("%s", v);
n = strlen(v);
if ( n == n1 )
{
for ( i = 0; i < n; ++i )
v2[i] = v[i];
encode(v2, n, k);
for ( i_0 = 0; i_0 < n; ++i_0 )
{
if ( *((_DWORD *)p_v1 + i_0) != v2[i_0] )
goto LABEL_2;
}
printf("Your input is the right answer!");
system("pause");
return 0;
}
else
{
LABEL_2:
printf("Wrong answer!");
system("pause");
return 0;
}
}
就只有一个encode函数加密,点进去看下,感觉像是xxtea加密的变种
void __cdecl encode(int *v, int n, const int *key)
{
int *v4; // rax
int *v5; // rax
int y; // [rsp+8h] [rbp-18h]
int e; // [rsp+Ch] [rbp-14h]
int rounds; // [rsp+10h] [rbp-10h]
int p; // [rsp+14h] [rbp-Ch]
int sum; // [rsp+18h] [rbp-8h]
int z; // [rsp+1Ch] [rbp-4h]
rounds = 52 / n + 6;
sum = 0;
for ( z = v[n - 1]; rounds--; z = *v5 )
{
sum -= 0x61C88647;
e = (sum >> 2) & 3;
for ( p = 0; p < n - 1; ++p )
{
y = v[p + 1];
v4 = &v[p];
*v4 += ((y ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
z = *v4;
}
v5 = &v[n - 1];
*v5 += ((*v ^ sum) + (z ^ key[e ^ p & 3])) ^ (((4 * *v) ^ (z >> 5)) + ((*v >> 3) ^ (16 * z)));
}
}
网上嫖了个脚本,改了改
#include
#include
#include
#define MX ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)))
#define DELTA 0x61C88647
int main()
{
int key[5] = {73,83,67,67};
int v2[20] = {0};
v2[0] = 0x8D7FFB13;
v2[1] = 0x8B2B6DB0;
v2[2] = 0x66C4403F;
v2[3] = 0x7413DD82;
v2[4] = 0xDBF303FC;
v2[5] = 0x417C54F3;
v2[6] = 0x428681FC;
v2[7] = 0xDE6B433E;
v2[8] = 0x88CD333A;
v2[9] = 0x94D6827;
v2[10] = 0x735F04B0;
v2[11] = 0x96FAB237;
v2[12] = 0xF5ED4CB2;
v2[13] = 0xC31F6C6D;
v2[14] = 0x94CDE5C0;
v2[15] = 0x43F04FD1;
v2[16] = 0xDEFD4947;
v2[17] = 0xE9366C1;
// n = 18
int sum = 0 , n = 18;
int rounds = 52 / n + 6;
int i,j,k;
int z,y,e,p;
sum = rounds * DELTA * (-1);
y = v2[0];
do
{
e = (sum >> 2) & 3;
for (p=n-1; p>0; p--)
{
z = v2[p-1];
//y = v2[p] -= ((y ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * y) ^ (z >> 5)) + ((y >> 3) ^ (16 * z)));
y = v2[p] -= MX;
}
z = v2[n-1];
//y = v2[0] -= ((v2[0] ^ sum) + (z ^ key[e ^ (p & 3)])) ^ (((4 * v2[0]) ^ (z >> 5)) + ((v2[0] >> 3) ^ (16 * z)));
y = v2[0] -= MX;
sum += DELTA;
}
while (--rounds);
for(i = 0 ; i < 18 ; i++)
{
printf("%c",v2[i],v2[i]);
}
return 0;
}
运行结果:
先看下信息
定位到主函数,这个的代码也是很简洁
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
__int64 v4; // rax
int v5; // ecx
char Destination[60]; // [esp+D8h] [ebp-348h] BYREF
int k; // [esp+114h] [ebp-30Ch]
char v8; // [esp+120h] [ebp-300h]
char v9[49]; // [esp+121h] [ebp-2FFh] BYREF
size_t v10; // [esp+15Ch] [ebp-2C4h]
int j; // [esp+168h] [ebp-2B8h]
int i; // [esp+174h] [ebp-2ACh]
char v13[56]; // [esp+180h] [ebp-2A0h] BYREF
__int64 v14[10]; // [esp+1B8h] [ebp-268h] BYREF
int v15; // [esp+208h] [ebp-218h]
int v16; // [esp+20Ch] [ebp-214h]
char Str[516]; // [esp+218h] [ebp-208h] BYREF
v15 = 0;
v16 = 0;
memset(v14, 0, 72);
memset(v13, 0, 45);
j__printf(&byte_439F18);
sub_413834((va_list)"%s", (char)Str); // 输入函数到Str中
if ( j__strlen(Str) != 32 )
return 0;
for ( i = 0; i < 8; ++i )
{
for ( j = 0; j < 4; ++j )
v13[5 * i + j] = Str[4 * i + j]; // 四个一组存入到二维数组 v13中
}
v10 = 0;
v8 = 0;
j__memset(v9, 0, sizeof(v9));
for ( k = 0; k < 8; ++k )
{
memset(Destination, 0, 50);
sub_4130CD((int)&v13[5 * k], Destination);
v10 = j__strlen(Destination);
v4 = sub_413BDB(v10, Destination, v15, v16);
v5 = k;
LODWORD(v14[k]) = v4;
HIDWORD(v14[v5]) = HIDWORD(v4);
}
if ( v14[2] + 7 * v14[1] - 4 * v14[0] - 2 * v14[3] == 0x2060BF585i64
&& 5 * v14[3] + 3 * v14[2] - v14[1] - 2 * v14[0] == 0x164D5CCD0i64
&& 2 * v14[1] + 8 * v14[3] + 10 * v14[0] - 5 * v14[2] == 0x449C83E5Ei64
&& 7 * v14[0] + 15 * v14[1] - 3 * v14[3] - 2 * v14[2] == 0x7B13C2C5Di64 )
{
if ( 15 * v14[4] + 35 * v14[7] - v14[5] - v14[6] == 0xF919FB032i64
&& 38 * v14[6] + v14[4] + v14[7] - 24 * v14[5] == 0x7060508FAi64
&& 38 * v14[5] + 32 * v14[4] - v14[6] - v14[7] == 0x124F561560i64
&& v14[4] + 41 * v14[6] - v14[5] - 25 * v14[7] == 0x51C97373Ei64 )
{
j__printf("Correct!\n");
}
else
{
j__printf("Keep trying!\n");
}
}
else
{
j__printf("Wrong!\n");
}
j__system("pause");
return 0;
}
这里有个==sub_413BDB(v10, Destination, v15, v16);==函数,其实这个就是将16进制转换为10进制而已
for ( k = 0; k < 8; ++k )
{
memset(Destination, 0, 50);
sub_4130CD((int)&v13[5 * k], Destination);
v10 = j__strlen(Destination);
v4 = sub_413BDB(v10, Destination, v15, v16);
v5 = k;
LODWORD(v14[k]) = v4;
HIDWORD(v14[v5]) = HIDWORD(v4);
}
转为10进制后然后返回成字符串的形式
__int64 __cdecl sub_414A20(int a1, int a2)
{
int j; // [esp+D4h] [ebp-30h]
int i; // [esp+E0h] [ebp-24h]
__int64 v5; // [esp+ECh] [ebp-18h]
int v6; // [esp+FCh] [ebp-8h]
__int64 v8; // [esp+114h] [ebp+10h]
v8 = 0i64;
for ( i = 0; *(_BYTE *)(i + a2); ++i )
{
switch ( *(_BYTE *)(i + a2) ) // 将16进制0-A转成0到16
{
case 'A':
v6 = 10;
break;
case 'B':
v6 = 11;
break;
case 'C':
v6 = 12;
break;
case 'D':
v6 = 13;
break;
case 'E':
v6 = 14;
break;
case 'F':
v6 = 15;
break;
default:
v6 = *(char *)(i + a2) - '0';
break;
}
v5 = 1i64;
for ( j = 0; j < a1 - 1 - i; ++j ) // 16进制转10进制
v5 = (unsigned __int64)((double)v5 * 16.0);
v8 += v6 * v5;
}
return v8;
}
一看这一堆等式,第一个想到的就是z3,写个脚本
from z3 import *
v = [Int(('v%d'% i)) for i in range(8) ]
s = Solver()
s.add(v[2] + 7 * v[1] - 4 * v[0] - 2 * v[3] == 0x2060BF585)
s.add(5 * v[3] + 3 * v[2] - v[1] - 2 * v[0] == 0x164D5CCD0)
s.add(2 * v[1] + 8 * v[3] + 10 * v[0] - 5 * v[2] == 0x449C83E5E)
s.add(7 * v[0] + 15 * v[1] - 3 * v[3] - 2 * v[2] == 0x7B13C2C5D)
s.add(15 * v[4] + 35 * v[7] - v[5] - v[6] == 0xF919FB032)
s.add(38 * v[6] + v[4] + v[7] - 24 * v[5] == 0x7060508FA)
s.add(38 * v[5] + 32 * v[4] - v[6] - v[7] == 0x124F561560)
s.add(v[4] + 41 * v[6] - v[5] - 25 * v[7] == 0x51C97373E)
s.check()
m = s.model()
print(m)
for i in range(8):
print(int(str(m[v[i]])))
result = [0] * 8
k = 0
for i in range(8):
result[i] = str(hex(int(str(m[v[i]])))).replace("0x","")
#change(result[i])
s = result[i]
for j in range(0,8,2):
print(chr(int(s[j:j+2],16)),end='')
print(result)
运行结果
[v3 = 1194153047,
v5 = 1095576901,
v7 = 1448236925,
v4 = 1245988943,
v0 = 1230193475,
v2 = 1515214414,
v6 = 1414878529,
v1 = 2069321031]
1230193475
2069321031
1515214414
1194153047
1245988943
1095576901
1414878529
1448236925
ISCC{WUGZPVNG-TWJDHOAM-ETUUAVRW}['49534343', '7b575547', '5a50564e', '472d5457', '4a44484f', '414d2d45', '54555541', '5652577d']
最终flag:ISCC{WUGZPVNG-TWJDHOAM-ETUUAVRW}
先查壳
这题找到主函数乍一眼看得我一脸懵,后面一点一点分析看了俩小时给看出来了,都是一边看一边猜的
__int64 __fastcall main(int a1, char **a2, char **a3)
{
__int64 v3; // rdx
bool v4; // bl
__int64 v5; // rax
__int64 v6; // rdx
__int64 v7; // rax
__int64 v8; // rdx
__int64 v9; // rax
__int64 v10; // rsi
__int64 v11; // rdx
__int64 v12; // rax
char v14; // [rsp+Fh] [rbp-1E1h] BYREF
char v15[32]; // [rsp+10h] [rbp-1E0h] BYREF
char v16[32]; // [rsp+30h] [rbp-1C0h] BYREF
int v17[8]; // [rsp+50h] [rbp-1A0h] BYREF
char v18[32]; // [rsp+70h] [rbp-180h] BYREF
char v19[32]; // [rsp+90h] [rbp-160h] BYREF
char v20[32]; // [rsp+B0h] [rbp-140h] BYREF
char v21[32]; // [rsp+D0h] [rbp-120h] BYREF
char v22[32]; // [rsp+F0h] [rbp-100h] BYREF
char v23[32]; // [rsp+110h] [rbp-E0h] BYREF
char v24[32]; // [rsp+130h] [rbp-C0h] BYREF
char v25[136]; // [rsp+150h] [rbp-A0h] BYREF
unsigned __int64 v26; // [rsp+1D8h] [rbp-18h]
v26 = __readfsqword(0x28u);
v17[0] = 1;
v17[1] = 2;
v17[2] = 3;
v17[3] = 4;
v17[4] = 5;
v17[5] = 6;
v17[6] = 7;
std::allocator<char>::allocator(v16, a2, a3);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v18, "ISCCYES", v16);
std::allocator<char>::~allocator(v16);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v19);
std::operator<<<std::char_traits<char>>(&std::cout, "id: ");// 输入id到v19中
std::operator>><char>(&std::cin, v19);
std::istream::get((std::istream *)&std::cin);
sub_4A5A((__int64)v25, (__int64)v19); // 对v19进行变换后存入v25中
std::allocator<char>::allocator(v16, v19, v3);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(
v20,
"cfe6902ba6404626f1bcabc81e72767b",
v16);
std::allocator<char>::~allocator(v16);
sub_4CE4(v24, v25); // 对v25进行变换后存入v24中
v4 = (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(v24, v20) == 0;// id = cfe6902ba6404626f1bcabc81e72767b
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
if ( v4 )
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v21);
v5 = std::operator<<<std::char_traits<char>>(&std::cout, "Please give me the flag:");
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
std::operator>><char>(&std::cin, v21);
std::allocator<char>::allocator(v16, v21, v6);// 输入flag到v21中
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v24, "{", v16);// 取{位置的指针
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, v21);
sub_2A5F(v15, v23, v24); // 取flag中{之前的字符串到v15中,v24感觉像个临时变量,啥东西都往里面存
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
std::allocator<char>::~allocator(v16);
v7 = sub_38CA(v15); // v7 = ISCC
if ( (unsigned __int8)sub_38F4(v7, "ISCC") )// 比较
{
std::allocator<char>::allocator(&v14, "ISCC", v8);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v24, "}", &v14);// 取}位置的指针
v9 = sub_391E(v15); //
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, v9);
sub_2A5F(v16, v23, v24);
v10 = sub_38CA(v16); // v10和v16还是flag
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v21, v10);// 拷贝给v21
sub_3704(v16);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
std::allocator<char>::~allocator(&v14);
std::allocator<char>::allocator(&v14, v10, v11);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v23, "4", &v14);// 取4位置的指针
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v22, v19);// v19是id,将id拷贝给v22
sub_2A5F(v16, v22, v23); // 取id中4之前的字符串到v16
v12 = sub_38CA(v16);
std::operator+<char>(v24, v21, v12); // 将v21和v12拷贝到v24中
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(v21, v24);// 将v24中的内容拷贝到v21
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
sub_3704(v16);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v22);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v23);
std::allocator<char>::~allocator(&v14);
sub_2914(v21, v17); // 加密
sub_29C9(v24, v21, v18); // base加密
if ( (unsigned int)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(
v24,
"rJFsLqVyFKZ7nl1Zgrs4C LsCGyEjHm6HPmmCrv=") )// flag内容
std::operator<<<std::char_traits<char>>(&std::cout, "Wrong!");
else
std::operator<<<std::char_traits<char>>(&std::cout, "Correct!");
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v24);
}
else
{
std::operator<<<std::char_traits<char>>(&std::cout, "head! head! head!");
}
sub_3704(v15);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v21);
}
else
{
std::operator<<<std::char_traits<char>>(&std::cout, "You don't have permission to acess the file!");
}
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v20);
sub_3636(v25);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v19);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v18);
return 0LL;
}
仔细分析一下,大概流程是这样的:先输入id -> 对id进行变换 -> 输入flag -> 提取出{} 中的内容 -> 取一段变换后的id,将其添加到前一步得到的字符串末尾->进行加密
这里有两个加密函数,从后往前分析
先分析sub_29C9(v24, v21, v18);
// a3 = "ISCCYES"
__int64 __fastcall sub_29C9(__int64 a1, __int64 a2, __int64 a3)
{
char v5[40]; // [rsp+20h] [rbp-40h] BYREF
unsigned __int64 v6; // [rsp+48h] [rbp-18h]
v6 = __readfsqword(0x28u);
sub_27C6(v5, a2);
sub_2569(a1, v5, a3); // v5为flag base加密后的结果
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v5);
return a1;
}
sub_27C6(v5, a2);
是魔改的base64加密
aAbcdefghijklmn db ‘ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/’
__int64 __fastcall sub_27C6(__int64 a1, __int64 a2)
{
int v3; // [rsp+14h] [rbp-1Ch]
int v4; // [rsp+18h] [rbp-18h]
int i; // [rsp+1Ch] [rbp-14h]
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(a1);
v3 = 0;
v4 = -6u;
for ( i = 0;
i < (unsigned __int64)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a2);
++i )
{
v3 = (v3 << 8)
+ *(char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
for ( v4 += 8; v4 >= 0; v4 -= 6 )
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(
a1,
(unsigned int)aAbcdefghijklmn[(v3 >> v4) & 0x3F]);
}
if ( v4 >= -5 )
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(
a1,
(unsigned int)aAbcdefghijklmn[(v3 << 8 >> (v4 + 8)) & 0x3F]);
while ( (std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a1) & 3) != 0 )
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::push_back(a1, 61LL);
return a1;
}
简洁一点写是这样的,看不出来没关系,带个字符串直接给他运行一下就清楚了
v3 = 0;
v4 = -6;
a2[] = {};
for (i = 0 ; i < strlen(a2) ; i++)
{
v3 = (v3 << 8) + a2[i]
for (v4 += 8; v4 >=0 ; v4 -= 6)
{
a2 += base[(v3 >> v4) & 0x3F];
}
}
if (v4 > -5)
a2 += base[(v3 << 8 >> (v4 + 8 )) & 0x3F];
a2 += '='
每三位字符加密后得到四位字符,最后用“=”填充
可以写出一个爆破脚本出来
v3 = 0
v4 = -6
i = 0
for i in range(0,len(flag_encode_2),4):
for j1 in range(32,128): #爆破第一位
temp1 = ((v3 << 8) + j1) % (2**32)
if flag_encode_2[i] == base[(temp1 >> 2) & 0x3F]:
#if i == 20 : print("temp1 = ",temp1)
for j2 in range(32,128): #爆破第二位
temp2 = ((temp1 << 8) + j2) % (2 ** 32)
if flag_encode_2[i + 1] == base[(temp2 >> 4) &0x3F]:
#if i == 20 : print("temp2 = ",temp2)
if i <= 32:
for j3 in range(32,128):
temp3 = ((temp2 << 8) + j3) % (2 ** 32)
if (flag_encode_2[i + 2] == base[(temp3 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == base[temp3 & 0x3F]):
flag_encode_1.append(j1)
flag_encode_1.append(j2)
flag_encode_1.append(j3)
v3 = temp3
print("i=",i,"v3=",v3)
else:
temp3 =temp2
if (flag_encode_2[i + 2] == base[(temp3 << 8 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == ord('=')):
flag_encode_1.append(j1)
flag_encode_1.append(j2)
v3 = temp3
print("i=",i,"v3=",v3)
sub_2569(a1, v5, a3);
是做的一个替换加密
__int64 __fastcall sub_2569(__int64 a1, __int64 a2, __int64 a3)
{
__int64 v3; // rdx
char *v4; // rax
char *v6; // rax
int v7; // ebx
char *v8; // rax
unsigned __int64 v9; // rbx
unsigned __int64 v10; // rax
_BYTE *v11; // rbx
char v14; // [rsp+23h] [rbp-4Dh] BYREF
int i; // [rsp+24h] [rbp-4Ch]
int v16; // [rsp+28h] [rbp-48h]
int v17; // [rsp+2Ch] [rbp-44h]
char v18[40]; // [rsp+30h] [rbp-40h] BYREF
unsigned __int64 v19; // [rsp+58h] [rbp-18h]
v19 = __readfsqword(0x28u);
v16 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a2);// v16为flag的长度
v17 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(a3);// a3 = "ISCCYES"
std::allocator<char>::allocator(&v14, a2, v3);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(a1, v16, 120LL, &v14);
std::allocator<char>::~allocator(&v14);
sub_2447(v18, a2, a3); // 将a3的值循环赋值给v18
for ( i = 0; i < v16; ++i )
{
v4 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
if ( isalnum(*v4)
|| *(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i) == 32 )// 如果是数字或者字母以及空格
{
v6 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
v7 = sub_23D9((unsigned int)*v6); // 返回和在unk_10280中相等的数的下标
v8 = (char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
(__int64)v18,
i);
v9 = (int)(v7 + sub_23D9((unsigned int)*v8));
v10 = std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::size(&unk_10280);
v11 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](
(__int64)&unk_10280,
v9 % v10);
}
else
{
v11 = (_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a2, i);
}
*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a1, i) = *v11;
}
*(_BYTE *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](a1, i) = 0;
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v18);
return a1;
}
依旧是可以写个爆破脚本出来
def find(temp):
if(temp in unk_10280):
return unk_10280.index(temp)
else:
return -1
for i in range(len(Str)):
for j in range(32,128):
if (j in range(48,58)) or (j in range(65,91)) or (j in range(97,123)) or (j == ord(" ")):
v7 = find(j)
v8 = v18[i]
v9 = v7 + find(v8)
v11 = unk_10280[v9 % len(unk_10280)]
else:
v11 = j
if v11 == Str[i]:
flag_encode_2.append(j)
print(i)
break
unk_10280的值,直接点击跳转是看不到unk_10280的值的,需要按x查看这个数组的交叉引用,然后一个一个找到给它赋值的地方
sub_2914(v21, v17)
这个就比较简单了,只是做了一个异或变换
v17 = [1,2,3,4,5,6,7]
for i in range(len(flag_encode_1)):
flag_encode_1[i] = flag_encode_1[i] ^ v17[i % 7]
print(chr(flag_encode_1[i]),end="")
然后得出总脚本
import base64
unk_10280 = [ord(i) for i in "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "]
base = [ord(i) for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"]
Str = [ord(i) for i in "rJFsLqVyFKZ7nl1Zgrs4C LsCGyEjHm6HPmmCrv="]
t = [ord(i) for i in "ISCCYES"]
v18 = []
flag = []
flag_encode_1 = []
flag_encode_2 = []
for i in range(len(Str)):
v18.append(t[i % 7])
print("v18 = ",v18)
#解密1,爆破
def find(temp):
if(temp in unk_10280):
return unk_10280.index(temp)
else:
return -1
for i in range(len(Str)):
for j in range(32,128):
if (j in range(48,58)) or (j in range(65,91)) or (j in range(97,123)) or (j == ord(" ")):
v7 = find(j)
v8 = v18[i]
v9 = v7 + find(v8)
v11 = unk_10280[v9 % len(unk_10280)]
else:
v11 = j
if v11 == Str[i]:
flag_encode_2.append(j)
print(i)
break
print("flag_encode_2 = ",flag_encode_2)
#第二次解密
v3 = 0
v4 = -6
i = 0
for i in range(0,len(flag_encode_2),4):
for j1 in range(32,128): #爆破第一位
temp1 = ((v3 << 8) + j1) % (2**32)
if flag_encode_2[i] == base[(temp1 >> 2) & 0x3F]:
#if i == 20 : print("temp1 = ",temp1)
for j2 in range(32,128): #爆破第二位
temp2 = ((temp1 << 8) + j2) % (2 ** 32)
if flag_encode_2[i + 1] == base[(temp2 >> 4) &0x3F]:
#if i == 20 : print("temp2 = ",temp2)
if i <= 32:
for j3 in range(32,128):
temp3 = ((temp2 << 8) + j3) % (2 ** 32)
if (flag_encode_2[i + 2] == base[(temp3 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == base[temp3 & 0x3F]):
flag_encode_1.append(j1)
flag_encode_1.append(j2)
flag_encode_1.append(j3)
v3 = temp3
print("i=",i,"v3=",v3)
else:
temp3 =temp2
if (flag_encode_2[i + 2] == base[(temp3 << 8 >> 6) & 0x3F]) and (flag_encode_2[i + 3] == ord('=')):
flag_encode_1.append(j1)
flag_encode_1.append(j2)
v3 = temp3
print("i=",i,"v3=",v3)
print("flag_encode_1 = ",flag_encode_1)
v17 = [1,2,3,4,5,6,7]
for i in range(len(flag_encode_1)):
flag_encode_1[i] = flag_encode_1[i] ^ v17[i % 7]
print(chr(flag_encode_1[i]),end="")
运行结果:
Reverse-aSOd9FAV-1l8P2GGVTIPO
然后这段字符是加了一部分的id在里面的,但是id的加密太麻烦了,看不出来,也不知道加了几位到后面,所以只需要从后往前依次减去一位字符,然后提交看对不对
最终测试的结果是减去了四位字符,最终flag: ISCC{Reverse-aSOd9FAV-1l8P2GGV}
这题确实挺简单的,看懂逻辑就行
还是先定位到主函数,然后分析一下(
其实也没啥好分析的
int __cdecl main_0(int argc, const char **argv, const char **envp)
{
int v4; // [esp+DCh] [ebp-E98h]
int v5; // [esp+E8h] [ebp-E8Ch]
char Str2[1112]; // [esp+F4h] [ebp-E80h] BYREF
char flag_encode_4[520]; // [esp+54Ch] [ebp-A28h] BYREF
char flag_encode_3[520]; // [esp+754h] [ebp-820h] BYREF
char flag_encode_2[520]; // [esp+95Ch] [ebp-618h] BYREF
char flag_encode_1[520]; // [esp+B64h] [ebp-410h] BYREF
char flag[516]; // [esp+D6Ch] [ebp-208h] BYREF
memset(flag, 0, 512);
memset(flag_encode_1, 0, 512);
memset(flag_encode_2, 0, 512);
memset(flag_encode_3, 0, 512);
memset(flag_encode_4, 0, 512);
memset(&Str2[592], 0, 512);
memset(&Str2[72], 0, 512);
j__printf(&byte_430F98);
sub_411721((va_list)"%s", (char)flag); // 输入flag到Str中
strcpy(Str2, ".W1BqthGbfjhXoLGaBiU1f.2XRoFtXXG15VMBuoM1VojNpgMl4XivlghXwoF0.");
v5 = j__strlen(flag);
sub_4116C7((int)flag, v5, (int)flag_encode_1, 0);// base64加密
v4 = j__strlen(flag_encode_1);
sub_411389((int)flag_encode_1, v4, (int)flag_encode_2, 1);// 变表base64加密
sub_411023((int)flag_encode_2, (int)flag_encode_3, 46, 0);// 在下标为0的位置加一个.
sub_411023((int)flag_encode_3, (int)flag_encode_4, 46, 22);// 在下标为22的位置加一个.
sub_4116E0(flag_encode_4, 2); // 字母表往后循环2位
if ( !j__strcmp(flag_encode_4, Str2) )
j__printf("flag is Correct!\n");
else
j__printf("flag is wrong!\n");
j__system("pause");
return 0;
}
写出脚本,第一次base64就是正常的base64加密,所以base1是多余的,然后要去掉0位和22位的那两个 .,我就手动去掉了
import base64
#base表
base1="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
base2 = [ord(i) for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"]
#将base2的表进行还原
for i in range(5,19):
temp = base2[i]
base2[i] = base2[i + 26]
base2[i+26] = temp
print("base2=",base2)
Str2 = list("W1BqthGbfjhXoLGaBiU1f2XRoFtXXG15VMBuoM1VojNpgMl4XivlghXwoF0.")
print("Str2=",Str2)
flag = "" #存储flag
flag_encode_1 = []
flag_encode_2 = [0]*len(Str2)
flag_encode_3 = [0]*len(Str2)
flag_encode_4 = [0]*len(Str2)
#第一次解密,往前循环两位
for i in range(len(Str2)):
t = ord(Str2[i])
if( t >= 97 ) and (t <= 122):
flag_encode_4[i]=(t - 2 - 97) % 26 + 97
elif(t >= 65) and (t <= 90):
flag_encode_4[i] = (t - 2 - 65) % 26 + 65
else:
flag_encode_4[i] = t
print("flag_encode_4 = ",flag_encode_4)
flag_encode_2 = flag_encode_4
print("flag_encode_2=",flag_encode_2)
#第四次解密 变表base
for i in range(0,len(Str2),4): #四位四位加密
for j1 in range(32,127): #爆破第一位
if base2[ (j1 & 0xFC) >> 2] == flag_encode_2[i]: #第一位相等
#if i==56: print(56)
v9 = 16 * (j1 & 3)
for j2 in range(32,127): #爆破第二位
if flag_encode_2[i + 1] == base2[((j2 & 0xF0) >> 4) + v9]:
#if i==56: print(56)
v10 = 4 * (j2 & 0xF)
if i <= 52:
for j3 in range(32,127): #爆破第三位
if (flag_encode_2[i + 2] == base2[v10 + ((j3 & 0xC0) >> 6 ) ] and (flag_encode_2[i + 3] == base2[j3 & 0x3F])):
if i==56: print(56)
print(i)
flag_encode_1.append(j1)
flag_encode_1.append(j2)
flag_encode_1.append(j3)
else:
if (flag_encode_2[i+2] == base2[v10]) and (flag_encode_2[i+3] == ord(".")):
print(i)
flag_encode_1.append(j1)
flag_encode_1.append(j2)
print("flag_encode_1 = ",flag_encode_1)
for i in range(len(flag_encode_1)):
flag+=chr(flag_encode_1[i])
print(base64.b64decode(flag))
运行结果:
base2= [65, 66, 67, 68, 69, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99, 100, 101, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 116, 117, 118, 119, 120, 121, 122, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 45, 95]
Str2= ['W', '1', 'B', 'q', 't', 'h', 'G', 'b', 'f', 'j', 'h', 'X', 'o', 'L', 'G', 'a', 'B', 'i', 'U', '1', 'f', '2', 'X', 'R', 'o', 'F', 't', 'X', 'X', 'G', '1', '5', 'V', 'M', 'B', 'u', 'o', 'M', '1', 'V', 'o', 'j', 'N', 'p', 'g', 'M', 'l', '4', 'X', 'i', 'v', 'l', 'g', 'h', 'X', 'w', 'o', 'F', '0', '.']
flag_encode_4 = [85, 49, 90, 111, 114, 102, 69, 122, 100, 104, 102, 86, 109, 74, 69, 121, 90, 103, 83, 49, 100, 50, 86, 80, 109, 68, 114, 86, 86, 69, 49, 53, 84, 75, 90, 115, 109, 75, 49, 84, 109, 104, 76, 110, 101, 75, 106, 52, 86, 103, 116, 106, 101, 102, 86, 117, 109, 68, 48, 46]
flag_encode_2= [85, 49, 90, 111, 114, 102, 69, 122, 100, 104, 102, 86, 109, 74, 69, 121, 90, 103, 83, 49, 100, 50, 86, 80, 109, 68, 114, 86, 86, 69, 49, 53, 84, 75, 90, 115, 109, 75, 49, 84, 109, 104,
76, 110, 101, 75, 106, 52, 86, 103, 116, 106, 101, 102, 86, 117, 109, 68, 48, 46]
0
4
8
12
16
20
24
28
32
36
40
44
48
52
56
flag_encode_1 = [83, 86, 78, 68, 81, 51, 116, 113, 85, 50, 49, 50, 100, 107, 53, 119, 101, 105, 48, 52, 85, 84, 77, 121, 78, 70, 82, 50, 77, 83, 48, 121, 77, 122, 66, 120, 84, 107, 73, 120, 85, 110, 48, 61]
b'ISCC{jSmvvNpz-8Q324Tv1-230qNB1R}'
最终flag:ISCC{jSmvvNpz-8Q324Tv1-230qNB1R}
代码逻辑挺简单的,分析如下
private boolean Jformat(String arg10) {
String v0 = "";
String v1 = "\n";
int v2 = arg10.lastIndexOf("_"); //取得最后一个"_"的下标
if(v2 == -1) {
return 0;
}
if(arg10.length() < 10) { // flag长度大于10
return 0;
}
int v4 = 5;
if(!arg10.substring(0, v4).equals("ISCC{")) {
return 0;
}
if(arg10.charAt(arg10.length() - 1) != 0x7D) { // 右括号
return 0;
}
++v2;
//从截取v2到字符串末尾调用Jlast加密,解密的结果为kit
if(!this.Jlast(arg10.substring(v2, arg10.length() - 1))) { // 最后一个单词为 kit
return 0;
}
try { //AES加密
byte[] v5 = new String(Base64.encode("K@e2022%%y".getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).getBytes(StandardCharsets.UTF_8); // 将 \n 替换
byte[] v7 = new String(Base64.encode("I&V2022***".getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).getBytes(StandardCharsets.UTF_8);
byte[] v10_1 = arg10.substring(v4, v2).getBytes(StandardCharsets.UTF_8);
SecretKeySpec v2_1 = new SecretKeySpec(v5, "AES");
IvParameterSpec v4_1 = new IvParameterSpec(v7);
Cipher v5_1 = Cipher.getInstance("AES/CBC/PKCS7Padding");
v5_1.init(1, ((Key)v2_1), ((AlgorithmParameterSpec)v4_1));
if(!new String(Base64.encode(Base64.encodeToString(v5_1.doFinal(v10_1), 2).getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).equals("SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0=")) {
return 0;
}
}
catch(Exception v10) {
v10.printStackTrace();
return 0;
}
return 1;
}
private boolean Jlast(String arg8) {
try {
MessageDigest v1 = MessageDigest.getInstance("MD5");
new BASE64Encoder();
arg8 = BASE64Encoder.encode(v1.digest(arg8.getBytes("utf-8")));
if(arg8.length() != 24) { // MD5加密再base64加密后长度为24
return 0;
}
char[] v1_1 = new char[arg8.length()];
int v2 = 5;
int v3 = 0;
int v4 = 0;
while(v2 >= 0) {
int v6 = 3;
if(v3 == 0) {
while(v6 >= 0) {
v1_1[v4] = arg8.charAt(v6 * 6 + v2);
++v4;
--v6;
}
v3 = 1;
}
else {
for(v3 = 0; v3 <= v6; ++v3) {
v1_1[v4] = arg8.charAt(v3 * 6 + v2);
++v4;
}
v3 = 0;
}
--v2;
}
if(!String.valueOf(v1_1).equals("=emd9M4=wlKEBdOFiCJ6/GTB")) {
return 0;
}
从截取v2到字符串末尾调用Jlast加密,解密的结果为kit
写个解密脚本
#include
#include
#include
int main()
{
char Str[] = "=emd9M4=wlKEBdOFiCJ6/GTB";
char Str2[33];
int v2 = 5;
int v3 = 0;
int v4 = 0;
char flag[33];
while(v2 >= 0 )
{
int v6 = 3;
if(v3 == 0)
{
while(v6 >=0 )
{
flag[v6 * 6 + v2] = Str[v4++];
--v6;
}
v3 = 1;
}
else
{
for(v3 = 0; v3 <= v6; ++v3)
{
flag[v3 * 6 + v2] = Str[v4++];
}
v3 = 0;
}
--v2;
}
for(int i = 0 ; i < strlen(Str); i++)
{
printf("%c",flag[i]);
}
return 0;
}
将得到的结果进行md5解密,得到kit
然后看最后的解密条件,逆着来就行
if(!new String(Base64.encode(Base64.encodeToString(v5_1.doFinal(v10_1), 2).getBytes(StandardCharsets.UTF_8), 0)).replace(((CharSequence)v1), ((CharSequence)v0)).equals("SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0="))
import base64
from Crypto.Cipher import AES
s = "SS90YmE3M2hUc0lVVCs1ZkZhWW0vNGl1dVNPWkc0UVdTaXlXN29GcDRvdz0="
s1 = base64.b64decode(s.encode('utf-8'))
s2 = base64.b64decode(s1) #s2就是密文
print("s2=",s2)
#password = b'S0BlMjAyMiUleQ==' #秘钥
password = base64.b64encode("K@e2022%%y".encode('utf-8'))
#iv = b'SSZWMjAyMioqKg==' #偏移量
iv = base64.b64encode("I&V2022***".encode('utf-8'))
aes = AES.new(password,AES.MODE_CBC,iv)
text = aes.decrypt(s2)
print(text)
text1=bytes.decode(text).rstrip("\x01").\
rstrip("\x02").rstrip("\x03").rstrip("\x04").rstrip("\x05").\
rstrip("\x06").rstrip("\x07").rstrip("\x08").rstrip("\x09").\
rstrip("\x0a").rstrip("\x0b").rstrip("\x0c").rstrip("\x0d").\
rstrip("\x0e").rstrip("\x0f").rstrip("\x10")
print(text1)
最终flag: