参考博客
输入类型的题目
没有很大的隐藏
显而易见的三个加密函数
第一个函数
看一眼255联想到rc4
我也对rc4没有完全了解,但是这么短肯定不是全部操作
但是也还好
我们输入是s,s作为参数是只有第二个第三个函数
所以第一个函数应该是初始化,而且因为没有根据我们输入来加密,所以一个动调就可以知道他干了啥
第二个函数,wp说是rc4
我还是看不懂
但是我知道绿色那一步才是最终操作,上面都是什么变换什么的
还是可以动调解决拿到异或的key
这里动调利用idapython!
动调一下就知道
edx是我们需要的key,esi是我们输入的
import idaapi
# 假设我们有一个eax的值
val = idaapi.get_reg_val("edx")
print(hex(val),end=',')
(注释不用管)
这样我们动调一遍,就可以知道key值
记得输入的'flag'长一点,这样才能全
第三段代码
_DWORD *__fastcall sub_4008FA(__int64 a1, int a2, const char *a3, _DWORD *a4)
{
int v4; // eax
int v5; // eax
unsigned __int8 v6; // al
int v7; // eax
unsigned __int8 v8; // al
int v9; // eax
int v10; // edx
_DWORD *result; // rax
char v13; // [rsp+2Dh] [rbp-13h]
unsigned __int8 v14; // [rsp+2Eh] [rbp-12h]
unsigned __int8 v15; // [rsp+2Fh] [rbp-11h]
int v16; // [rsp+30h] [rbp-10h]
int v17; // [rsp+34h] [rbp-Ch]
v16 = 0;
v17 = 0;
while ( v17 < a2 )
{
v4 = v17++;
v13 = *(v4 + a1);
if ( v17 >= a2 )
{
v6 = 0;
}
else
{
v5 = v17++;
v6 = *(v5 + a1);
}
v14 = v6;
if ( v17 >= a2 )
{
v8 = 0;
}
else
{
v7 = v17++;
v8 = *(v7 + a1);
}
v15 = v8;
a3[v16] = ((v13 >> 2) & 0x3F) + 61;
a3[v16 + 1] = (((v14 >> 4) | (16 * v13)) & 0x3F) + 61;
a3[v16 + 2] = (((v8 >> 6) | (4 * v14)) & 0x3F) + 61;
v9 = v16 + 3;
v16 += 4;
a3[v9] = (v15 & 0x3F) + 61;
}
if ( a2 % 3 == 1 )
{
a3[--v16] = 61;
}
else if ( a2 % 3 != 2 )
{
goto LABEL_15;
}
a3[v16 - 1] = 61;
LABEL_15:
v10 = strlen(a3);
result = a4;
*a4 = v10;
return result;
}
其实结合最后的密文你就知道,肯定和base64有关,首先也没找到换表什么的
base64的代码,我只是了解
就像RC4的255是个标志
这里Base64的 &0x3f(保证在64之内,0x3f就是63),标志
base64标志算法里面这后面应该是 base64table[ ]
这样的形式,但是这里没有!
so,上半身的base64吧,编码了一下
import base64
v9=[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,0xaf,0xe9,0xce,0xda,0x67,0x39,0xba,0x3b,0x85,0xeb,0xd2,0x6b,0xab,0x6,0x6b,0x10,0x57,0x2c,0x88,0x70,0xf7,0x4f,0xaa,0x7f,0x12,0x47,0xd6,0xde,0x74,0xb2,0x1d,0xa4,0xd7,0x76,0x9a,0xe0,0xb6,0x71,0x25,0xdf,0x60,0x34,0x38,0xc4,0x66,0x51,0xe4,0x25,0x48,0xbe,0x17,0xf5,0x38,0x21,0xe5,0xd8,0xa8,0xe5,0x24,0x31,0x98,0x3d,0x72,0xe7,0x8f,0x92,0x53,0xad,0x96,0x6b,0x14,0xf2,0x14,0x31,0x23,0x83,0x9,0x27,0xf9,0x5a,0xed,0x8d,0x51,0xd9,0xd5,0x44,0xc2,0x70,0x22,0x63,0x80,0x4a,0x3d,0xb,0x22,0x52,0xc8,0x7b,0xf0,0x54,0xf,0xf4,0x6,0xb3,0x6d,0x42,0x18,0x9b,0x60,0x11,0x2f,0x2d,0x27,0xfa,0xdd,0xa2,0x4c,0x3c,0x2b,0xc0,0x60,0xe6,0xbd,]
data = [0x5a, 0x60, 0x54, 0x7A, 0x7A, 0x54, 0x72, 0x44, 0x7C, 0x66, 0x51, 0x50, 0x5B, 0x5F, 0x56, 0x56,
0x4C, 0x7C, 0x79, 0x6E, 0x65, 0x55, 0x52, 0x79, 0x55, 0x6D, 0x46, 0x6B, 0x6C, 0x56, 0x4A, 0x67,
0x4C, 0x61, 0x73, 0x4A, 0x72, 0x6F, 0x5A, 0x70, 0x48, 0x52, 0x78, 0x49, 0x55, 0x6c, 0x48, 0x5C,
0x76, 0x5A, 0x45, 0x3D]
# 考虑填充符的影响,计算实际的解码长度
padding = (len(data) % 4)
if padding:
data += [0x3D] * (4 - padding)
flag = ''
for i in range(0, len(data), 4):
# 解码前三个字符
b1 = (((data[i] - 0x3D) & 0x3F) << 2) | (((data[i + 1] - 0x3D) & 0x30) >> 4)
b2 = (((data[i + 1] - 0x3D) & 0x0F) << 4) | (((data[i + 2] - 0x3D) & 0x3C) >> 2)
b3 = (((data[i + 2] - 0x3D) & 0x03) << 6) | ((data[i + 3] - 0x3D) & 0x3F)
# 如果有填充符,跳过最后的字节
if padding == 1 and i >= len(data) - 4:
flag += chr(b1)
elif padding == 2 and i >= len(data) - 8:
flag += chr(b1) + chr(b2)
else:
flag += chr(b1) + chr(b2) + chr(b3)
print(flag)
for i in range(len(flag)-1):
print(chr((ord(flag[i])^(v9[i]))),end='')
这里解码我没不会,保存下这个代码吧~