love----bugku
1.下载文件,看到是一个程序,直接ida打开,这里用32位,不然看不了反编译。(我电脑是缺少文件打开程序不了,所以我们就跳过查看程序,直接进入分析)
2.使用shift+F12查看字符串,
反编译代码如下:
int __cdecl sub_4156E0()
{
size_t v0; // eax@6
const char *v1; // eax@6
size_t v2; // eax@9
char v4; // [sp+Ch] [bp-17Ch]@1
size_t v5; // [sp+10h] [bp-178h]@3
size_t j; // [sp+DCh] [bp-ACh]@6
size_t i; // [sp+E8h] [bp-A0h]@1
char Str1[108]; // [sp+F4h] [bp-94h]@5
char Str; // [sp+160h] [bp-28h]@6
char v10; // [sp+17Ch] [bp-Ch]@6
unsigned int v11; // [sp+184h] [bp-4h]@1
int v12; // [sp+188h] [bp+0h]@1 ###定义各种变量的类型
memset(&v4, -858993460, 0x17Cu);
v11 = (unsigned int)&v12 ^ __security_cookie;
for ( i = 0; (signed int)i < 100; ++i )
{
v5 = i;
if ( i >= 0x64 )
sub_411154();
Str1[v5] = 0;
}
sub_41132F("please enter the flag:");
sub_411375("%20s", &Str);
v0 = j_strlen(&Str);
v1 = (const char *)sub_4110BE(&Str, v0, &v10); ###再这里我们明确,用户的输入经过sub_4110BE这个函数的操作,进行了加密
strncpy(Str1, v1, 0x28u); ###将v1用户输入复制给str1
sub_411127();
i = j_strlen(Str1);
for ( j = 0; (signed int)j < (signed int)i; ++j ) ##此处我们看到j比用户输入的i长度小的时候,会遍历用户输入的str1,循环一次之后使用j之前+1
Str1[j] += j; ##用书输入的str1中的j位等于j+1
v2 = j_strlen(Str1); ###将str1的长度给v2
strncmp(Str1, "e3nifIH9b_C@n@dH", v2); ##比较str1和"e3nifIH9b_C@n@dH"比较,并且对比str1的长度,如果相同则输出flag,不同则错误
if ( sub_411127() )
sub_41132F("wrong flag!\n");
else
sub_41132F("rigth flag!\n");
sub_41126C();
sub_411280();
return sub_411127();
}
加密函数的内容:
int __cdecl sub_411AB0(int a1, unsigned int a2, int a3)
{
int v4; // [sp+Ch] [bp-100h]@1
int v5; // [sp+D4h] [bp-38h]@7
int i; // [sp+E0h] [bp-2Ch]@7
unsigned int v7; // [sp+ECh] [bp-20h]@1
void *Dst; // [sp+F8h] [bp-14h]@1
int v9; // [sp+104h] [bp-8h]@1 ##也是初始定义了一些变量值,我们要注意a2是用户的输入
memset(&v4, -858993460, 0x100u);
v9 = 0;
Dst = 0;
v7 = 0;
if ( a1 && a2 )
{
v7 = a2 / 3;
if ( (signed int)(a2 / 3) % 3 )
++v7;
v7 *= 4;
*(_DWORD *)a3 = v7;
malloc(v7 + 1);
Dst = (void *)sub_411127();
if ( Dst )
{
j_memset(Dst, 0, v7 + 1);
v9 = a1;
v7 = a2;
i = 0;
v5 = 0;
while ( (signed int)v7 > 0 )
{
byte_41A144[2] = 0;
byte_41A144[1] = 0;
byte_41A144[0] = 0;
for ( i = 0; i < 3 && (signed int)v7 >= 1; ++i )
{
byte_41A144[i] = *(_BYTE *)v9;
--v7;
++v9;
}
if ( !i )
break;
v4 = i;
if ( i == 1 )
{
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
}
else
{
if ( v4 == 2 )
{
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[64];
}
else
{
if ( v4 == 3 )
{
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)];
*((_BYTE *)Dst + v5++) = aAbcdefghijklmn[byte_41A144[2] & 0x3F];
}
}
}
}
*((_BYTE *)Dst + v5) = 0;
}
}
return sub_411127();
}
我们看到此处结果是经过了base64解密了的,也就是说我们输入的东西,经过加密函数操作,变成e3nifIH9b_C@n@dH,进行比较,如果相同,那么输出flag正确,用户的输入再经过base64解码就是flag了。所以接下来我们需要写一个脚本模拟这个情况,前提是我们要看懂加密函数才能正确写出脚本。我此时太菜,看不懂加密函数,所以只要看别人的脚本。才懂得加密函数大概就是用户原来的输入假入是bc,bc再ascii码62和63,因为b在0位置,所以63+0再转ascii,同理63代表c,在位置1,所以63+1等于64为d,依次类推,这就是加密函数的作用,结果就得e3nifIH9b_C@n@dH,所以我们脚本要反其道而行:
解码得出flag