-
-
[原创]2019看雪CTF 晋级赛Q1 第6题
-
发表于: 2019-3-23 16:53 3200
-
一、main函数如下:
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 | int __cdecl main( int argc, const char **argv, const char **envp) { int v3; // ecx unsigned int v4; // ebx char *Str; // [esp+0h] [ebp-68h] char v7[4]; // [esp+10h] [ebp-58h] char constKey[32]; // [esp+20h] [ebp-48h] char inputSn; // [esp+40h] [ebp-28h] sub_404930(0x10u, v3, ( int )Str); sub_4044B0(); v4 = 0; *(_DWORD *)constKey = 0x7F79745E; *(_DWORD *)&constKey[4] = 0x2B704C63; *(_DWORD *)&constKey[8] = 0x612B5347; // ^ty.cLp+GS+aGQ-GV(lGJ}y))AGS+ae *(_DWORD *)&constKey[12] = 0x472D5147; *(_DWORD *)&constKey[16] = 0x476C2856; *(_DWORD *)&constKey[20] = 695827786; *(_DWORD *)&constKey[24] = 1397178665; *(_DWORD *)&constKey[28] = 0x65612B; strcpy (v7, "Ansome_Is_Wrong" ); while ( v4 < strlen (constKey) ) { constKey[v4] ^= 0x18u; // Flag{Th3_K3y_I5_N0t_Rea11Y_K3y}. ++v4; } puts ( "Please Input Your Key_ Now!" ); scanf ( "%s" , &inputSn); if ( check1(&inputSn) ) { check2(&inputSn); system ( "pause" ); } else { puts (v7); } return 0; } |
1、初始化一些常量
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 | int __cdecl main( int argc, const char **argv, const char **envp) { int v3; // ecx unsigned int v4; // ebx char *Str; // [esp+0h] [ebp-68h] char v7[4]; // [esp+10h] [ebp-58h] char constKey[32]; // [esp+20h] [ebp-48h] char inputSn; // [esp+40h] [ebp-28h] sub_404930(0x10u, v3, ( int )Str); sub_4044B0(); v4 = 0; *(_DWORD *)constKey = 0x7F79745E; *(_DWORD *)&constKey[4] = 0x2B704C63; *(_DWORD *)&constKey[8] = 0x612B5347; // ^ty.cLp+GS+aGQ-GV(lGJ}y))AGS+ae *(_DWORD *)&constKey[12] = 0x472D5147; *(_DWORD *)&constKey[16] = 0x476C2856; *(_DWORD *)&constKey[20] = 695827786; *(_DWORD *)&constKey[24] = 1397178665; *(_DWORD *)&constKey[28] = 0x65612B; strcpy (v7, "Ansome_Is_Wrong" ); while ( v4 < strlen (constKey) ) { constKey[v4] ^= 0x18u; // Flag{Th3_K3y_I5_N0t_Rea11Y_K3y}. ++v4; } puts ( "Please Input Your Key_ Now!" ); scanf ( "%s" , &inputSn); if ( check1(&inputSn) ) { check2(&inputSn); system ( "pause" ); } else { puts (v7); } return 0; } |
1、初始化一些常量
2、读取sn
3、调用check1进行校验,返回0,则退出。
4、调用check2进行校验。然后暂停。
二、check1函数
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 | signed int __cdecl check1( char *inputSn) { signed int index; // ecx signed int v2; // edx signed int result; // eax int v4; // [esp+0h] [ebp-38h] int v5; // [esp+4h] [ebp-34h] int v6; // [esp+8h] [ebp-30h] char v7; // [esp+Ch] [ebp-2Ch] int v8; // [esp+10h] [ebp-28h] int v9; // [esp+14h] [ebp-24h] int v10; // [esp+18h] [ebp-20h] int v11; // [esp+1Ch] [ebp-1Ch] int v12; // [esp+20h] [ebp-18h] index = 8; v2 = 0; v8 = 0x72756F59; v9 = 0x706E495F; v10 = 0x495F7475; v11 = 0x72575F73; v12 = 0x676E6F; v4 = 811151704; v5 = 0x74334E75; v6 = 0x64303047; v7 = 0; while ( *((_BYTE *)&v4 + v2) == inputSn[index] ) // X1Y0uN3tG00d { ++v2; ++index; if ( v2 > 11 ) { result = 1; if ( inputSn[20] == 'H' ) return result; return 0; } } return 0; } |
1、初始化一些常量字符串,然后从输入sn第9个字符开始比较,一共比较11次。
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 | signed int __cdecl check1( char *inputSn) { signed int index; // ecx signed int v2; // edx signed int result; // eax int v4; // [esp+0h] [ebp-38h] int v5; // [esp+4h] [ebp-34h] int v6; // [esp+8h] [ebp-30h] char v7; // [esp+Ch] [ebp-2Ch] int v8; // [esp+10h] [ebp-28h] int v9; // [esp+14h] [ebp-24h] int v10; // [esp+18h] [ebp-20h] int v11; // [esp+1Ch] [ebp-1Ch] int v12; // [esp+20h] [ebp-18h] index = 8; v2 = 0; v8 = 0x72756F59; v9 = 0x706E495F; v10 = 0x495F7475; v11 = 0x72575F73; v12 = 0x676E6F; v4 = 811151704; v5 = 0x74334E75; v6 = 0x64303047; v7 = 0; while ( *((_BYTE *)&v4 + v2) == inputSn[index] ) // X1Y0uN3tG00d { ++v2; ++index; if ( v2 > 11 ) { result = 1; if ( inputSn[20] == 'H' ) return result; return 0; } } return 0; } |
1、初始化一些常量字符串,然后从输入sn第9个字符开始比较,一共比较11次。
2、可知sn格式如下 xxxxxxxxX1Y0uN3tG00dxxxx
3、要求sn第20位置为字符'H',因此 sn为
xxxxxxxxX1Y0uN3tG00dHxxx
三、check2函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int __cdecl check2( char *inputKey) { char Dest; // [esp+8h] [ebp-10h] if ( strlen (inputKey) == 24 ) { if ( check3(inputKey) ) { inputKey[20] -= 'X' ; inputKey[21] -= 'F' ; inputKey[22] -= 3; inputKey[23] -= 'k' ; strcpy (&Dest, inputKey); } } else { printf ( "String Length is Wrong" ); } return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | int __cdecl check2( char *inputKey) { char Dest; // [esp+8h] [ebp-10h] if ( strlen (inputKey) == 24 ) { if ( check3(inputKey) ) { inputKey[20] -= 'X' ; inputKey[21] -= 'F' ; inputKey[22] -= 3; inputKey[23] -= 'k' ; strcpy (&Dest, inputKey); } } else { printf ( "String Length is Wrong" ); } return 0; } |
1、可知sn长度为24,格式为:
xxxxxxxxX1Y0uN3tG00dHxxx
2、调用check3函数。如果check3函数返回0,则表示sn不正确。
3、如果check3函数返回1 ,则对sn的后4位进行修改,同时将sn拷贝到一个局部变量中。
4、可以看出sn长度为24,而局部变量buf长度为0x14,因此会造成栈溢出,恰好sn后四个字节会覆盖返回地址。
四、check3函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | signed int __cdecl check3( char *inputKey) { int v1; // ebx int v2; // ecx int v3; // esi signed int result; // eax changeFirst8(inputKey); v1 = g_first8Sn3 + 1000 * g_first8Sn0[0] + 100 * g_first8Sn1 + 10 * g_first8Sn2; v2 = g_first8Sn5 + 10 * g_first8Sn4; v3 = g_first8Sn7 + 10 * g_first8Sn6; if ( 2 * (v1 + v2) != 4040 || 3 * v2 / 2 + 100 * v3 != 115 ) goto LABEL_2; result = 1; if ( v1 - 110 * v3 != 1900 ) { printf ( "Key_Is_Wrong,Please_Input_Again!" ); LABEL_2: result = 0; } return result; } |
调用 changeFirst8(inputKey);对前8个字符统一减去0x30。
可以看出check3是对前8个字符进行校验的。看起来是个类似方程组。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | signed int __cdecl check3( char *inputKey) { int v1; // ebx int v2; // ecx int v3; // esi signed int result; // eax changeFirst8(inputKey); v1 = g_first8Sn3 + 1000 * g_first8Sn0[0] + 100 * g_first8Sn1 + 10 * g_first8Sn2; v2 = g_first8Sn5 + 10 * g_first8Sn4; v3 = g_first8Sn7 + 10 * g_first8Sn6; if ( 2 * (v1 + v2) != 4040 || 3 * v2 / 2 + 100 * v3 != 115 ) goto LABEL_2; result = 1; if ( v1 - 110 * v3 != 1900 ) { printf ( "Key_Is_Wrong,Please_Input_Again!" ); LABEL_2: result = 0; } return result; } |
调用 changeFirst8(inputKey);对前8个字符统一减去0x30。
可以看出check3是对前8个字符进行校验的。看起来是个类似方程组。
最后于 2019-3-23 17:17
被ODPan编辑
,原因:
赞赏
他的文章
看原图
赞赏
雪币:
留言: