-
-
[原创] 第五题:魅影舞姬
-
发表于: 2019-9-17 10:48 3192
-
首先对输入的长度限定
std::string::string((std::string *)&serial); 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 *)&serial); std::string::operator+=(&serial, "Welcome/to/this/very/simple/challenge"); if ( (unsigned __int64)std::string::length((std::string *)&serial) > 85 )//输入加上一字符串的长度要<=85 即输入<=48 { v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!"); std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system("pause"); }
然后调用check_fun函数进行检验,(函数内可以看到有生成随机数,输入作为种子,和btea算法,这里并不是关键,调试时过掉,先分析之后的算法)
std::string::string((std::string *)&serial); 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 *)&serial); std::string::operator+=(&serial, "Welcome/to/this/very/simple/challenge"); if ( (unsigned __int64)std::string::length((std::string *)&serial) > 85 )//输入加上一字符串的长度要<=85 即输入<=48 { v3 = std::operator<<<std::char_traits<char>>(refptr__ZSt4cout, "incorrect!"); std::ostream::operator<<(v3, refptr__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_); system("pause"); }
然后调用check_fun函数进行检验,(函数内可以看到有生成随机数,输入作为种子,和btea算法,这里并不是关键,调试时过掉,先分析之后的算法)
_BOOL1 __fastcall check_fun(__int64 a1) { char *v1; // rax int r3; // eax char v4; // [rsp+20h] [rbp-60h] unsigned int v5; // [rsp+9F0h] [rbp+970h] int v6; // [rsp+9F4h] [rbp+974h] int v7; // [rsp+A04h] [rbp+984h] int r2; // [rsp+A08h] [rbp+988h] unsigned int r1; // [rsp+A0Ch] [rbp+98Ch] v1 = (char *)std::string::operator[]((std::string *)a1, 0i64); std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::mersenne_twister_engine( &v4, (unsigned int)*v1); r1 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); r2 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); r3 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); v7 = r3; v5 = r1; v6 = r3; btea(&v5, 2, &MD5_Constants_475020); return r2 - (v5 + v6) == 0xA504A8F7;
下面程序流程:
_BOOL1 __fastcall check_fun(__int64 a1) { char *v1; // rax int r3; // eax char v4; // [rsp+20h] [rbp-60h] unsigned int v5; // [rsp+9F0h] [rbp+970h] int v6; // [rsp+9F4h] [rbp+974h] int v7; // [rsp+A04h] [rbp+984h] int r2; // [rsp+A08h] [rbp+988h] unsigned int r1; // [rsp+A0Ch] [rbp+98Ch] v1 = (char *)std::string::operator[]((std::string *)a1, 0i64); std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::mersenne_twister_engine( &v4, (unsigned int)*v1); r1 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); r2 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); r3 = std::mersenne_twister_engine<unsigned int,32ull,624ull,397ull,31ull,2567483615u,11ull,4294967295u,7ull,2636928640u,15ull,4022730752u,18ull,1812433253u>::operator()(&v4); v7 = r3; v5 = r1; v6 = r3; btea(&v5, 2, &MD5_Constants_475020); return r2 - (v5 + v6) == 0xA504A8F7;
下面程序流程:
输入+“Welcome/to/this/very/simple/challenge” 中截取36位--> base64_decode
(3des)
-->输入的[16:23]为key,对dest (解码结果的[18:])进行des_decode
-->再以输入的[8:15]为key,对上一步des解密结果进行加密
--> MD5(输入+“Welcome/to/this/very/simple/challenge” ) 后面会判断md5值是否为44e4403b63620a2075d3fb2e0a6207d2
-->最后以输入的[0:7]为key,再对上一步结果解密
-->加解密完成后,替换解码的[18:25]
-->进入主要的检验函数 check_de_Z9O0oOo0Oo0Ss
des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_16_23, &Dest); des_encode_Z9Ooo0OO0ooPKcPcS1_(&Dest, &s_8_15, &Dest); Str_lens = strlen(Str); md5(&str_md5, Str, Str_lens); des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_0_7, &Dest); std::string::replace((std::string *)&de_serial, 18ui64, 8ui64, &Dest); std::string::string((std::string *)&v37, (const std::string *)&de_serial); check_de_Z9O0oOo0Oo0Ss((unsigned __int64)&v37); std::string::~string((std::string *)&v37);
des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_16_23, &Dest); des_encode_Z9Ooo0OO0ooPKcPcS1_(&Dest, &s_8_15, &Dest); Str_lens = strlen(Str); md5(&str_md5, Str, Str_lens); des_decode_Z9Ooo0ooO0OPcS_S_(&Dest, &s_0_7, &Dest); std::string::replace((std::string *)&de_serial, 18ui64, 8ui64, &Dest); std::string::string((std::string *)&v37, (const std::string *)&de_serial); check_de_Z9O0oOo0Oo0Ss((unsigned __int64)&v37); std::string::~string((std::string *)&v37);
我们进入 check_de_Z9O0oOo0Oo0Ss
__int64 __fastcall check_de_Z9O0oOo0Oo0Ss(unsigned __int64 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 *a; // [rsp+80h] [rbp+0h] a = a1; std::string::substr((&v2 + 4), a1, 0i64, 6ui64);// 截取6个字符 count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v3);// 第一个迷宫 std::string::~string(&v3); modifi_maze_Z9O0oOo0Oo0ii(4, 5); // 交换4,5行 modifi_maze_Z9O0oOo0Oo0ii(9, 10); modifi_maze_Z9O0oOo0Oo0ii(10, 11); std::string::substr(&v4, a, 6ui64, 6ui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v4); std::string::~string(&v4); modifi_maze_Z9O0oOo0Oo0ii(5, 7); modifi_maze_Z9O0oOo0Oo0ii(9, 12); modifi_maze_Z9O0oOo0Oo0ii(11, 12); std::string::substr(&v5, a, 12ui64, 6ui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v5); std::string::~string(&v5); modifi_maze_Z9O0oOo0Oo0ii(2, 12); d_modifi_maze_Z9O0oOOo0o0ii(7, 9); // 第7行替换第9行 d_modifi_maze_Z9O0oOOo0o0ii(5, 3); d_modifi_maze_Z9O0oOOo0o0ii(5, 11); d_modifi_maze_Z9O0oOOo0o0ii(4, 7); d_modifi_maze_Z9O0oOOo0o0ii(4, 8); std::string::substr(&v6, a, 18ui64, 0xFFFFFFFFFFFFFFFFui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v6); return std::string::~string(&v6); }
查看迷宫的检验函数:
_BOOL8 __fastcall check_maze_Z9O0oO00ooOSs(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(&str_2_Oooo0O0Oo, '@', 0i64);// size_t find(char c,size_t pos = 0)const; // 找‘@’,起始位置 for ( i = 0i64; std::string::length(v7) > i; ++i ) { for ( j = 6; j >= 0; j -= 2 ) { v1 = (*std::string::operator[](v7, i) >> j) & 3;// 除64 16 4 1 与0011 保留低位 // 即一个字节8位,先取高两位,··· if ( v1 == 1 ) { v6 += 13; // 下移动 } else if ( v1 > 1 ) { if ( v1 == 2 ) { --v6; // 左移动 } else if ( v1 == 3 ) { // 3 右移动 ++v6; } } else if ( !v1 ) { v6 -= 13; // 0 上移 } v2 = *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '-' && *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '#'; if ( v2 ) return 0i64; // 最后是# } } return *std::string::operator[](&str_2_Oooo0O0Oo, v6) == '#'; }
检验之后迷宫会进行变换:
modifi_maze_Z9O0oOo0Oo0ii 进行两个行的交换
_d_modifi_maze_Z9O0oOOo0o0ii 参数2的行用参数1的行替换
一共有4个迷宫,到这里就应该很明朗了,输入36位,进行base64解码,前3个6字节对应前3个迷宫,最后的8字节经过3des加解密,对应最后一个迷宫
__int64 __fastcall check_de_Z9O0oOo0Oo0Ss(unsigned __int64 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 *a; // [rsp+80h] [rbp+0h] a = a1; std::string::substr((&v2 + 4), a1, 0i64, 6ui64);// 截取6个字符 count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v3);// 第一个迷宫 std::string::~string(&v3); modifi_maze_Z9O0oOo0Oo0ii(4, 5); // 交换4,5行 modifi_maze_Z9O0oOo0Oo0ii(9, 10); modifi_maze_Z9O0oOo0Oo0ii(10, 11); std::string::substr(&v4, a, 6ui64, 6ui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v4); std::string::~string(&v4); modifi_maze_Z9O0oOo0Oo0ii(5, 7); modifi_maze_Z9O0oOo0Oo0ii(9, 12); modifi_maze_Z9O0oOo0Oo0ii(11, 12); std::string::substr(&v5, a, 12ui64, 6ui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v5); std::string::~string(&v5); modifi_maze_Z9O0oOo0Oo0ii(2, 12); d_modifi_maze_Z9O0oOOo0o0ii(7, 9); // 第7行替换第9行 d_modifi_maze_Z9O0oOOo0o0ii(5, 3); d_modifi_maze_Z9O0oOOo0o0ii(5, 11); d_modifi_maze_Z9O0oOOo0o0ii(4, 7); d_modifi_maze_Z9O0oOOo0o0ii(4, 8); std::string::substr(&v6, a, 18ui64, 0xFFFFFFFFFFFFFFFFui64); count_O0ooOO00o += check_maze_Z9O0oO00ooOSs(&v6); return std::string::~string(&v6); }
查看迷宫的检验函数:
_BOOL8 __fastcall check_maze_Z9O0oO00ooOSs(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(&str_2_Oooo0O0Oo, '@', 0i64);// size_t find(char c,size_t pos = 0)const; // 找‘@’,起始位置 for ( i = 0i64; std::string::length(v7) > i; ++i ) { for ( j = 6; j >= 0; j -= 2 ) { v1 = (*std::string::operator[](v7, i) >> j) & 3;// 除64 16 4 1 与0011 保留低位 // 即一个字节8位,先取高两位,··· if ( v1 == 1 ) { v6 += 13; // 下移动 } else if ( v1 > 1 ) { if ( v1 == 2 ) { --v6; // 左移动 } else if ( v1 == 3 ) { // 3 右移动 ++v6; } } else if ( !v1 ) { v6 -= 13; // 0 上移 } v2 = *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '-' && *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '#'; if ( v2 ) return 0i64; // 最后是# } } return *std::string::operator[](&str_2_Oooo0O0Oo, v6) == '#'; }
检验之后迷宫会进行变换:
_BOOL8 __fastcall check_maze_Z9O0oO00ooOSs(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(&str_2_Oooo0O0Oo, '@', 0i64);// size_t find(char c,size_t pos = 0)const; // 找‘@’,起始位置 for ( i = 0i64; std::string::length(v7) > i; ++i ) { for ( j = 6; j >= 0; j -= 2 ) { v1 = (*std::string::operator[](v7, i) >> j) & 3;// 除64 16 4 1 与0011 保留低位 // 即一个字节8位,先取高两位,··· if ( v1 == 1 ) { v6 += 13; // 下移动 } else if ( v1 > 1 ) { if ( v1 == 2 ) { --v6; // 左移动 } else if ( v1 == 3 ) { // 3 右移动 ++v6; } } else if ( !v1 ) { v6 -= 13; // 0 上移 } v2 = *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '-' && *std::string::operator[](&str_2_Oooo0O0Oo, v6) != '#'; if ( v2 ) return 0i64; // 最后是# } } return *std::string::operator[](&str_2_Oooo0O0Oo, v6) == '#'; }
检验之后迷宫会进行变换:
modifi_maze_Z9O0oOo0Oo0ii 进行两个行的交换
_d_modifi_maze_Z9O0oOOo0o0ii 参数2的行用参数1的行替换
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
他的文章
- [原创]KCTF 2024 第十题 试探 1984
- KCTF2023第五题 争分夺秒 9501
- KCTF2022第三题 石像病毒 7282
- [原创]KCTF2021春季赛第四题 英雄救美 10009
- [原创] 第五题:魅影舞姬 3193
看原图
赞赏
雪币:
留言: