-
-
[原创] 看雪.安恒2020 KCTF春季赛 > 第二题 子鼠开天 WP
-
发表于: 2020-4-17 00:59 4042
-
本题是考密码学,用到了AES,RSA,SHA512,MD5,不过算法还是很简单的,只要RSA的大数分解能完成,就很容易做出来,分析如下:
IDA中F5,主函数:
int __cdecl main(int argc, const char **argv, const char **envp)
{
time_t v3; // eax
unsigned int v4; // kr04_4
int result; // eax
char v6; // [esp+8h] [ebp-12Ch]
char v7; // [esp+9h] [ebp-12Bh]
__int16 v8; // [esp+69h] [ebp-CBh]
char v9; // [esp+6Bh] [ebp-C9h]
char v10; // [esp+6Ch] [ebp-C8h]
char v11; // [esp+6Dh] [ebp-C7h]
__int16 v12; // [esp+131h] [ebp-3h]
char v13; // [esp+133h] [ebp-1h]
v6 = 0;
v10 = 0;
memset(&v7, 0, 0x60u);
v8 = 0;
v9 = 0;
memset(&v11, 0, 0xC4u);
v12 = 0;
v13 = 0;
v3 = time(0);
sub_411AD8(v3);
sub_411A90(aEnterYourName);
scanf(aS, &v6);
v4 = strlen(&v6) + 1;
if ( v4 - 1 < 3 || v4 - 1 > 0x14 ) //名字长度判断
{
sub_411A90(aBadName);
result = -1;
}
else
{
sub_411A90(aEnterYourSn);
scanf(aS, &v10);
if ( strlen(&v10) == 64 ) //SN长度判断
{
sub_401380((int)&v6, v4 - 1, (int)&v10, 64); //验证
result = 0;
}
else
{
sub_411A90(aBadSn);
result = -1;
}
}
return result;
}
可以看出输入的名字长度可以在3-20这间,SN长度为64,验证函数是sub_401380:
void __cdecl sub_401380(char *name, unsigned int lenName, char *sSn, int lenSN)
{
char v4; // [esp+4h] [ebp-70h]
BYTE sn2[32]; // [esp+14h] [ebp-60h]
BYTE sn[32]; // [esp+34h] [ebp-40h]
BYTE sn1[32]; // [esp+54h] [ebp-20h]
if ( lenName >= 3 && lenName <= 0x14 && lenSN == 64 )
{
if ( sub_401000(sSn, 64, (int)sn) != 32 // 16进制串sSn转BYTE sn[32]
|| (AESCode(sn, 32, (int)sn1, keyAES, 128, 0), RSACode((int)sn1, 32, (int)sn2), sn2[0])// sn2[0]要等于0
|| sn2[1] != 2 // sn2[1]要等于2
|| sn2[15] ) // sn2[15]要等于0,这儿sn2前16字节只判断了三个字节,另13个字节可以为任意,就出现了多解
{
sub_411A90(aBadSn);
}
else
{
hashCode(name, lenName, (int)&v4); // 计算name的hash值
if ( !memcmp(&v4, &sn2[16], 0x10u) ) // 比较sn2后16字节要等于name的hash
sub_411A90(aCongratulation); // 成功
}
}
}
AESCode是AES算法,通过一个函数,由参数bEncode来指定完成加密或解密
int __cdecl AESCode(BYTE *bufOut, int lenOut, BYTE *bufIn, BYTE *keyAES, int lenBit, BOOL bEncode)
{
BYTE *v6; // esi
int v7; // ebx
char v9; // [esp+4h] [ebp-F4h]
if ( bEncode == 1 ) // 同一个函数完成加密解密,由bEncode判断是加密还是解密
sub_404FE0(keyAES, lenBit, (unsigned int *)&v9);
else
sub_4053A0(keyAES, lenBit, (unsigned int *)&v9);
if ( lenOut / 16 <= 0 )
return lenOut;
v6 = bufOut;
v7 = lenOut / 16;
do
{
sub_404FB0(v6, &v6[bufIn - bufOut], &v9, bEncode);
v6 += 16;
--v7;
}
while ( v7 );
return lenOut;
}
RSACode对输入完成RSA解密,返回值高位在前
signed int __cdecl RSACode(BYTE *bufIn, int lenIn, BYTE *bufOut)
{
_DWORD *N; // esi
_DWORD *e; // edi
_DWORD *m; // ebx
_DWORD *c; // ebp
signed int v8; // eax
_DWORD *lpMem; // [esp+0h] [ebp-24h]
BYTE bN[32]; // [esp+4h] [ebp-20h]
BYTE *lenIna; // [esp+2Ch] [ebp+8h]
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
看原图
赞赏
雪币:
留言: