-
-
[原创]KCTF Q3 第五题:魅影舞姬
-
发表于: 2019-9-24 03:26 3312
-
IDA载入CM,粗略分析下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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | int __cdecl main( int argc, const char **argv, const char **envp) { __int64 v3; // rax _BOOL1 v4; // bl __int64 v5; // rax void *v6; // rsp size_t v7; // rbx const char *v8; // rax size_t v9; // rbx const char *v10; // rax size_t v11; // rbx const char *v12; // rax size_t v13; // rbx const char *v14; // rax size_t v15; // rbx const char *v16; // rax __int64 v17; // rax __int64 v18; // rax unsigned __int8 v20; // [rsp+20h] [rbp-60h] char v21; // [rsp+40h] [rbp-40h] char v22; // [rsp+50h] [rbp-30h] char input8; // [rsp+60h] [rbp-20h] char base64de; // [rsp+70h] [rbp-10h] unsigned __int64 v25; // [rsp+80h] [rbp+0h] unsigned __int64 v26; // [rsp+90h] [rbp+10h] char v27; // [rsp+A0h] [rbp+20h] char v28; // [rsp+B0h] [rbp+30h] char v29; // [rsp+C0h] [rbp+40h] char v30; // [rsp+D0h] [rbp+50h] char v31; // [rsp+E0h] [rbp+60h] char v32; // [rsp+F0h] [rbp+70h] char v33; // [rsp+100h] [rbp+80h] char v34; // [rsp+110h] [rbp+90h] char v35; // [rsp+120h] [rbp+A0h] char v36; // [rsp+130h] [rbp+B0h] char v37; // [rsp+140h] [rbp+C0h] int v38; // [rsp+14Ch] [rbp+CCh] char *Str; // [rsp+150h] [rbp+D0h] __int64 v40; // [rsp+158h] [rbp+D8h] _main(); std::string::string((std::string *)&v26); std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "please input your serial:\n" ); std::operator>>< char ,std::char_traits< char >,std::allocator< char >>(refptr__ZSt3cin, (std::string *)&v26); std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge" ); if ( (unsigned __int64 )std::string::length((std::string *)&v26) > 0x55 ) // 加上上面的字符串长度不大于0x55 { v3 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::string((std::string *)&v27, ( const std::string *)&v26); v4 = !check_fun(( __int64 )&v27); // 防多解,调试时可以先跳过 std::string::~string((std::string *)&v27); if ( v4 ) { v5 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::substr((std::string *)&v28, ( const std::string *)&v26, 0i64, 0x24ui64); // 取前36个字符 base64decode((std::string *)&v25, (std::string *)&v28); // base64解码 std::string::~string((std::string *)&v28); v40 = std::string::length((std::string *)&v26); v6 = alloca(16 * ((unsigned __int64 )(v40 + 16) >> 4)); Str = ( char *)&v20; std::string::substr((std::string *)&v29, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v7 = std::string::length((std::string *)&v29) + 1; std::string::substr((std::string *)&v30, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v8 = ( const char *)std::string::c_str((std::string *)&v30); strncpy (&base64de, v8, v7); std::string::~string((std::string *)&v30); std::string::~string((std::string *)&v29); std::string::substr((std::string *)&v31, ( const std::string *)&v26, 0i64, 8ui64); v9 = std::string::length((std::string *)&v31) + 1; std::string::substr((std::string *)&v32, ( const std::string *)&v26, 0i64, 8ui64); v10 = ( const char *)std::string::c_str((std::string *)&v32); strncpy (&input8, v10, v9); std::string::~string((std::string *)&v32); std::string::~string((std::string *)&v31); std::string::substr((std::string *)&v33, ( const std::string *)&v26, 8ui64, 8ui64); v11 = std::string::length((std::string *)&v33) + 1; std::string::substr((std::string *)&v34, ( const std::string *)&v26, 8ui64, 8ui64); v12 = ( const char *)std::string::c_str((std::string *)&v34); strncpy (&v22, v12, v11); std::string::~string((std::string *)&v34); std::string::~string((std::string *)&v33); std::string::substr((std::string *)&v35, ( const std::string *)&v26, 0x10ui64, 8ui64); v13 = std::string::length((std::string *)&v35) + 1; std::string::substr((std::string *)&v36, ( const std::string *)&v26, 0x10ui64, 8ui64); v14 = ( const char *)std::string::c_str((std::string *)&v36); strncpy (&v21, v14, v13); std::string::~string((std::string *)&v36); std::string::~string((std::string *)&v35); v15 = std::string::length((std::string *)&v26) + 1; v16 = ( const char *)std::string::c_str((std::string *)&v26); strncpy (Str, v16, v15); desdecrypt(&base64de, &v21, &base64de); // 用输入字符串的16-23位作为密钥解密 desencrypt(&base64de, &v22, &base64de); // 8-15 v38 = strlen (Str); md5(&v20, Str, v38); desdecrypt(&base64de, &input8, &base64de); // 0-7 std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de); std::string::string((std::string *)&v37, ( const std::string *)&v25); checkgame(( const std::string *)&v37); // 游戏 std::string::~string((std::string *)&v37); if ( (unsigned __int8 )std::operator==< char >(&v20, &strmd5) ) // 比较输入字符的MD5,防多解 { if ( checkresult == 4 ) // checkgame函数内检查成功则加1,一共检查4次 v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "correct!" ); else v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } else { v18 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } system ( "pause" ); std::string::~string((std::string *)&v20); std::string::~string((std::string *)&v25); } } std::string::~string((std::string *)&v26); return 0; } |
checkgame函数。
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 | __int64 __fastcall checkstr( const std::string *a1) { __int64 v2; // [rsp+0h] [rbp-80h] char v3; // [rsp+20h] [rbp-60h] char v4; // [rsp+30h] [rbp-50h] char v5; // [rsp+40h] [rbp-40h] char v6; // [rsp+50h] [rbp-30h] const std::string *v7; // [rsp+80h] [rbp+0h] v7 = a1; std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64); // 取base64解码后的6个字节 checkresult += (unsigned __int8 )check((std::string *)&v3); std::string::~string((std::string *)&v3); replacegame(4, 5); // 替换布局,后面都是 replacegame(9, 10); replacegame(10, 11); std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v4); std::string::~string((std::string *)&v4); replacegame(5, 7); replacegame(9, 12); replacegame(11, 12); std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v5); std::string::~string((std::string *)&v5); replacegame(2, 12); replace(7, 9); replace(5, 3); replace(5, 11); replace(4, 7); replace(4, 8); std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); checkresult += (unsigned __int8 )check((std::string *)&v6); return std::string::~string((std::string *)&v6); } |
check函数
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 41 42 | _BOOL8 __fastcall check(std::string *a1) { int v1; // eax _BOOL1 v2; // al signed int j; // [rsp+2Ch] [rbp-14h] unsigned __int64 i; // [rsp+30h] [rbp-10h] int v6; // [rsp+3Ch] [rbp-4h] std::string *v7; // [rsp+50h] [rbp+10h] v7 = a1; v6 = std::string::find((std::string *)&str, '@' , 0i64); // 从'@'开始 for ( i = 0i64; std::string::length(v7) > i; ++i ) // 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可 { for ( j = 6; j >= 0; j -= 2 ) { v1 = (( signed int )*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3; if ( v1 == 1 ) // down { v6 += 13; } else if ( v1 > 1 ) { if ( v1 == 2 ) // left { --v6; } else if ( v1 == 3 ) // right { ++v6; } } else if ( !v1 ) // up { v6 -= 13; } v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#' ; // '@'碰到'-'则失败 if ( v2 ) return 0i64; // '@'到达'#'则成功 } } return *(_BYTE *)std::string::operator[](&str, v6) == '#' ; } |
动态调试抓取到4个游戏布局,如下
*************
*@***********
*-***********
*--**----****
*-***-**-****
*-***#**-****
*--*****-****
**-*****-****
**-------****
**-*-----****
**---**-*****
**-****--****
*************
111113113333330000022211
*************
*@***********
*-***********
*-***-**-****
*--**----****
*-***#**-****
*--*****-****
**-*****-****
**-*-----****
**---**-*****
**-------****
**-****--****
*************
111113111330333300002221
*************
*@***********
*-***********
*-***-**-****
*--*****-****
*-***#**-****
*--**----****
**-*****-****
**-****--****
**---**-*****
**-*-----****
**-------****
*************
111113111331333003002220
*************
**-------****
*--*****-****
*-***-**-****
*--*****-****
*-***#**-****
*-***-**-****
*-***-**-****
*--**----****
**---**-*****
*--*****-****
*@***********
*************
03002000000303333331111111222000
最后一个并不是24步而是32步,将所有步数加起来除以4等于26。
前面用来base64解码的字符串有36个,如果没有"=",解码后的字节数是27个,所以flag有一个等号。
将步骤恢复成6个字节,再base64编码,注意后8个字节需要DES处理一下。
IDA载入CM,粗略分析下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 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | int __cdecl main( int argc, const char **argv, const char **envp) { __int64 v3; // rax _BOOL1 v4; // bl __int64 v5; // rax void *v6; // rsp size_t v7; // rbx const char *v8; // rax size_t v9; // rbx const char *v10; // rax size_t v11; // rbx const char *v12; // rax size_t v13; // rbx const char *v14; // rax size_t v15; // rbx const char *v16; // rax __int64 v17; // rax __int64 v18; // rax unsigned __int8 v20; // [rsp+20h] [rbp-60h] char v21; // [rsp+40h] [rbp-40h] char v22; // [rsp+50h] [rbp-30h] char input8; // [rsp+60h] [rbp-20h] char base64de; // [rsp+70h] [rbp-10h] unsigned __int64 v25; // [rsp+80h] [rbp+0h] unsigned __int64 v26; // [rsp+90h] [rbp+10h] char v27; // [rsp+A0h] [rbp+20h] char v28; // [rsp+B0h] [rbp+30h] char v29; // [rsp+C0h] [rbp+40h] char v30; // [rsp+D0h] [rbp+50h] char v31; // [rsp+E0h] [rbp+60h] char v32; // [rsp+F0h] [rbp+70h] char v33; // [rsp+100h] [rbp+80h] char v34; // [rsp+110h] [rbp+90h] char v35; // [rsp+120h] [rbp+A0h] char v36; // [rsp+130h] [rbp+B0h] char v37; // [rsp+140h] [rbp+C0h] int v38; // [rsp+14Ch] [rbp+CCh] char *Str; // [rsp+150h] [rbp+D0h] __int64 v40; // [rsp+158h] [rbp+D8h] _main(); std::string::string((std::string *)&v26); std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "please input your serial:\n" ); std::operator>>< char ,std::char_traits< char >,std::allocator< char >>(refptr__ZSt3cin, (std::string *)&v26); std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge" ); if ( (unsigned __int64 )std::string::length((std::string *)&v26) > 0x55 ) // 加上上面的字符串长度不大于0x55 { v3 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::string((std::string *)&v27, ( const std::string *)&v26); v4 = !check_fun(( __int64 )&v27); // 防多解,调试时可以先跳过 std::string::~string((std::string *)&v27); if ( v4 ) { v5 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::substr((std::string *)&v28, ( const std::string *)&v26, 0i64, 0x24ui64); // 取前36个字符 base64decode((std::string *)&v25, (std::string *)&v28); // base64解码 std::string::~string((std::string *)&v28); v40 = std::string::length((std::string *)&v26); v6 = alloca(16 * ((unsigned __int64 )(v40 + 16) >> 4)); Str = ( char *)&v20; std::string::substr((std::string *)&v29, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v7 = std::string::length((std::string *)&v29) + 1; std::string::substr((std::string *)&v30, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v8 = ( const char *)std::string::c_str((std::string *)&v30); strncpy (&base64de, v8, v7); std::string::~string((std::string *)&v30); std::string::~string((std::string *)&v29); std::string::substr((std::string *)&v31, ( const std::string *)&v26, 0i64, 8ui64); v9 = std::string::length((std::string *)&v31) + 1; std::string::substr((std::string *)&v32, ( const std::string *)&v26, 0i64, 8ui64); v10 = ( const char *)std::string::c_str((std::string *)&v32); strncpy (&input8, v10, v9); std::string::~string((std::string *)&v32); std::string::~string((std::string *)&v31); std::string::substr((std::string *)&v33, ( const std::string *)&v26, 8ui64, 8ui64); v11 = std::string::length((std::string *)&v33) + 1; std::string::substr((std::string *)&v34, ( const std::string *)&v26, 8ui64, 8ui64); v12 = ( const char *)std::string::c_str((std::string *)&v34); strncpy (&v22, v12, v11); std::string::~string((std::string *)&v34); std::string::~string((std::string *)&v33); std::string::substr((std::string *)&v35, ( const std::string *)&v26, 0x10ui64, 8ui64); v13 = std::string::length((std::string *)&v35) + 1; std::string::substr((std::string *)&v36, ( const std::string *)&v26, 0x10ui64, 8ui64); v14 = ( const char *)std::string::c_str((std::string *)&v36); strncpy (&v21, v14, v13); std::string::~string((std::string *)&v36); std::string::~string((std::string *)&v35); v15 = std::string::length((std::string *)&v26) + 1; v16 = ( const char *)std::string::c_str((std::string *)&v26); strncpy (Str, v16, v15); desdecrypt(&base64de, &v21, &base64de); // 用输入字符串的16-23位作为密钥解密 desencrypt(&base64de, &v22, &base64de); // 8-15 v38 = strlen (Str); md5(&v20, Str, v38); desdecrypt(&base64de, &input8, &base64de); // 0-7 std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de); std::string::string((std::string *)&v37, ( const std::string *)&v25); checkgame(( const std::string *)&v37); // 游戏 std::string::~string((std::string *)&v37); if ( (unsigned __int8 )std::operator==< char >(&v20, &strmd5) ) // 比较输入字符的MD5,防多解 { if ( checkresult == 4 ) // checkgame函数内检查成功则加1,一共检查4次 v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "correct!" ); else v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } else { v18 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } system ( "pause" ); std::string::~string((std::string *)&v20); std::string::~string((std::string *)&v25); } } std::string::~string((std::string *)&v26); return 0; } |
checkgame函数。
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | int __cdecl main( int argc, const char **argv, const char **envp) { __int64 v3; // rax _BOOL1 v4; // bl __int64 v5; // rax void *v6; // rsp size_t v7; // rbx const char *v8; // rax size_t v9; // rbx const char *v10; // rax size_t v11; // rbx const char *v12; // rax size_t v13; // rbx const char *v14; // rax size_t v15; // rbx const char *v16; // rax __int64 v17; // rax __int64 v18; // rax unsigned __int8 v20; // [rsp+20h] [rbp-60h] char v21; // [rsp+40h] [rbp-40h] char v22; // [rsp+50h] [rbp-30h] char input8; // [rsp+60h] [rbp-20h] char base64de; // [rsp+70h] [rbp-10h] unsigned __int64 v25; // [rsp+80h] [rbp+0h] unsigned __int64 v26; // [rsp+90h] [rbp+10h] char v27; // [rsp+A0h] [rbp+20h] char v28; // [rsp+B0h] [rbp+30h] char v29; // [rsp+C0h] [rbp+40h] char v30; // [rsp+D0h] [rbp+50h] char v31; // [rsp+E0h] [rbp+60h] char v32; // [rsp+F0h] [rbp+70h] char v33; // [rsp+100h] [rbp+80h] char v34; // [rsp+110h] [rbp+90h] char v35; // [rsp+120h] [rbp+A0h] char v36; // [rsp+130h] [rbp+B0h] char v37; // [rsp+140h] [rbp+C0h] int v38; // [rsp+14Ch] [rbp+CCh] char *Str; // [rsp+150h] [rbp+D0h] __int64 v40; // [rsp+158h] [rbp+D8h] _main(); std::string::string((std::string *)&v26); std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "please input your serial:\n" ); std::operator>>< char ,std::char_traits< char >,std::allocator< char >>(refptr__ZSt3cin, (std::string *)&v26); std::string::operator+=(&v26, "Welcome/to/this/very/simple/challenge" ); if ( (unsigned __int64 )std::string::length((std::string *)&v26) > 0x55 ) // 加上上面的字符串长度不大于0x55 { v3 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::string((std::string *)&v27, ( const std::string *)&v26); v4 = !check_fun(( __int64 )&v27); // 防多解,调试时可以先跳过 std::string::~string((std::string *)&v27); if ( v4 ) { v5 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v5, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system ( "pause" ); } else { std::string::substr((std::string *)&v28, ( const std::string *)&v26, 0i64, 0x24ui64); // 取前36个字符 base64decode((std::string *)&v25, (std::string *)&v28); // base64解码 std::string::~string((std::string *)&v28); v40 = std::string::length((std::string *)&v26); v6 = alloca(16 * ((unsigned __int64 )(v40 + 16) >> 4)); Str = ( char *)&v20; std::string::substr((std::string *)&v29, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v7 = std::string::length((std::string *)&v29) + 1; std::string::substr((std::string *)&v30, ( const std::string *)&v25, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); v8 = ( const char *)std::string::c_str((std::string *)&v30); strncpy (&base64de, v8, v7); std::string::~string((std::string *)&v30); std::string::~string((std::string *)&v29); std::string::substr((std::string *)&v31, ( const std::string *)&v26, 0i64, 8ui64); v9 = std::string::length((std::string *)&v31) + 1; std::string::substr((std::string *)&v32, ( const std::string *)&v26, 0i64, 8ui64); v10 = ( const char *)std::string::c_str((std::string *)&v32); strncpy (&input8, v10, v9); std::string::~string((std::string *)&v32); std::string::~string((std::string *)&v31); std::string::substr((std::string *)&v33, ( const std::string *)&v26, 8ui64, 8ui64); v11 = std::string::length((std::string *)&v33) + 1; std::string::substr((std::string *)&v34, ( const std::string *)&v26, 8ui64, 8ui64); v12 = ( const char *)std::string::c_str((std::string *)&v34); strncpy (&v22, v12, v11); std::string::~string((std::string *)&v34); std::string::~string((std::string *)&v33); std::string::substr((std::string *)&v35, ( const std::string *)&v26, 0x10ui64, 8ui64); v13 = std::string::length((std::string *)&v35) + 1; std::string::substr((std::string *)&v36, ( const std::string *)&v26, 0x10ui64, 8ui64); v14 = ( const char *)std::string::c_str((std::string *)&v36); strncpy (&v21, v14, v13); std::string::~string((std::string *)&v36); std::string::~string((std::string *)&v35); v15 = std::string::length((std::string *)&v26) + 1; v16 = ( const char *)std::string::c_str((std::string *)&v26); strncpy (Str, v16, v15); desdecrypt(&base64de, &v21, &base64de); // 用输入字符串的16-23位作为密钥解密 desencrypt(&base64de, &v22, &base64de); // 8-15 v38 = strlen (Str); md5(&v20, Str, v38); desdecrypt(&base64de, &input8, &base64de); // 0-7 std::string::replace((std::string *)&v25, 0x12ui64, 8ui64, &base64de); std::string::string((std::string *)&v37, ( const std::string *)&v25); checkgame(( const std::string *)&v37); // 游戏 std::string::~string((std::string *)&v37); if ( (unsigned __int8 )std::operator==< char >(&v20, &strmd5) ) // 比较输入字符的MD5,防多解 { if ( checkresult == 4 ) // checkgame函数内检查成功则加1,一共检查4次 v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "correct!" ); else v17 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v17, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } else { v18 = std::operator<<<std::char_traits< char >>(refptr__ZSt4cout, "incorrect!" ); std::ostream::operator<<(v18, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); } system ( "pause" ); std::string::~string((std::string *)&v20); std::string::~string((std::string *)&v25); } } std::string::~string((std::string *)&v26); return 0; } |
checkgame函数。
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 | __int64 __fastcall checkstr( const std::string *a1) { __int64 v2; // [rsp+0h] [rbp-80h] char v3; // [rsp+20h] [rbp-60h] char v4; // [rsp+30h] [rbp-50h] char v5; // [rsp+40h] [rbp-40h] char v6; // [rsp+50h] [rbp-30h] const std::string *v7; // [rsp+80h] [rbp+0h] v7 = a1; std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64); // 取base64解码后的6个字节 checkresult += (unsigned __int8 )check((std::string *)&v3); std::string::~string((std::string *)&v3); replacegame(4, 5); // 替换布局,后面都是 replacegame(9, 10); replacegame(10, 11); std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v4); std::string::~string((std::string *)&v4); replacegame(5, 7); replacegame(9, 12); replacegame(11, 12); std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v5); std::string::~string((std::string *)&v5); replacegame(2, 12); replace(7, 9); replace(5, 3); replace(5, 11); replace(4, 7); replace(4, 8); std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); checkresult += (unsigned __int8 )check((std::string *)&v6); return std::string::~string((std::string *)&v6); } |
check函数
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 | __int64 __fastcall checkstr( const std::string *a1) { __int64 v2; // [rsp+0h] [rbp-80h] char v3; // [rsp+20h] [rbp-60h] char v4; // [rsp+30h] [rbp-50h] char v5; // [rsp+40h] [rbp-40h] char v6; // [rsp+50h] [rbp-30h] const std::string *v7; // [rsp+80h] [rbp+0h] v7 = a1; std::string::substr((std::string *)(&v2 + 4), a1, 0i64, 6ui64); // 取base64解码后的6个字节 checkresult += (unsigned __int8 )check((std::string *)&v3); std::string::~string((std::string *)&v3); replacegame(4, 5); // 替换布局,后面都是 replacegame(9, 10); replacegame(10, 11); std::string::substr((std::string *)&v4, v7, 6ui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v4); std::string::~string((std::string *)&v4); replacegame(5, 7); replacegame(9, 12); replacegame(11, 12); std::string::substr((std::string *)&v5, v7, 0xCui64, 6ui64); checkresult += (unsigned __int8 )check((std::string *)&v5); std::string::~string((std::string *)&v5); replacegame(2, 12); replace(7, 9); replace(5, 3); replace(5, 11); replace(4, 7); replace(4, 8); std::string::substr((std::string *)&v6, v7, 0x12ui64, 0xFFFFFFFFFFFFFFFFui64); checkresult += (unsigned __int8 )check((std::string *)&v6); return std::string::~string((std::string *)&v6); } |
check函数
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 41 42 | _BOOL8 __fastcall check(std::string *a1) { int v1; // eax _BOOL1 v2; // al signed int j; // [rsp+2Ch] [rbp-14h] unsigned __int64 i; // [rsp+30h] [rbp-10h] int v6; // [rsp+3Ch] [rbp-4h] std::string *v7; // [rsp+50h] [rbp+10h] v7 = a1; v6 = std::string::find((std::string *)&str, '@' , 0i64); // 从'@'开始 for ( i = 0i64; std::string::length(v7) > i; ++i ) // 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可 { for ( j = 6; j >= 0; j -= 2 ) { v1 = (( signed int )*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3; if ( v1 == 1 ) // down { v6 += 13; } else if ( v1 > 1 ) { if ( v1 == 2 ) // left { --v6; } else if ( v1 == 3 ) // right { ++v6; } } else if ( !v1 ) // up { v6 -= 13; } v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#' ; // '@'碰到'-'则失败 if ( v2 ) return 0i64; // '@'到达'#'则成功 } } return *(_BYTE *)std::string::operator[](&str, v6) == '#' ; } |
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 41 42 | _BOOL8 __fastcall check(std::string *a1) { int v1; // eax _BOOL1 v2; // al signed int j; // [rsp+2Ch] [rbp-14h] unsigned __int64 i; // [rsp+30h] [rbp-10h] int v6; // [rsp+3Ch] [rbp-4h] std::string *v7; // [rsp+50h] [rbp+10h] v7 = a1; v6 = std::string::find((std::string *)&str, '@' , 0i64); // 从'@'开始 for ( i = 0i64; std::string::length(v7) > i; ++i ) // 一字节可以走4步,每次只有6字节(最后一个不是),所以在24步之内走到终点即可 { for ( j = 6; j >= 0; j -= 2 ) { v1 = (( signed int )*(unsigned __int8 *)std::string::operator[](v7, i) >> j) & 3; if ( v1 == 1 ) // down { v6 += 13; } else if ( v1 > 1 ) { if ( v1 == 2 ) // left { --v6; } else if ( v1 == 3 ) // right { ++v6; } } else if ( !v1 ) // up { v6 -= 13; } v2 = *(_BYTE *)std::string::operator[](&str, v6) != '-' && *(_BYTE *)std::string::operator[](&str, v6) != '#' ; // '@'碰到'-'则失败 if ( v2 ) return 0i64; // '@'到达'#'则成功 } } return *(_BYTE *)std::string::operator[](&str, v6) == '#' ; } |
动态调试抓取到4个游戏布局,如下
*************
*@***********
*-***********
*--**----****
*-***-**-****
*-***#**-****
*--*****-****
**-*****-****
**-------****
**-*-----****
**---**-*****
**-****--****
*************
111113113333330000022211
*************
*@***********
*-***********
*-***-**-****
*--**----****
*-***#**-****
*--*****-****
**-*****-****
**-*-----****
**---**-*****
**-------****
**-****--****
*************
111113111330333300002221
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
赞赏
雪币:
留言: