签到题,但做法不是很签到
三个判断输入三段字符串最后拿到完整flag
经过动调发现fun1函数是拿来比较的,在fun1入口把字符串copy下来就行了
flag1密文校验
_BOOL8 __usercall chk1@<rax>(YouWouldChk *this@<rdi>, __int64 a2@<rbp>, __m256i a3@<ymm7>)
{
__int128 v4; // [rsp-28h] [rbp-28h]
unsigned __int64 v5; // [rsp-10h] [rbp-10h]
__int64 v6; // [rsp-8h] [rbp-8h]
__asm { endbr64 }
v6 = a2;
v5 = __readfsqword(0x28u);
v4 = (unsigned __int64)'5a6bb29c';
std::operator<<<std::char_traits<char>>(&std::cout, "I drew a :", 0LL);
std::operator>><char,std::char_traits<char>>(&std::cin, YouWouldChk::chk1(void)::JC);
return (unsigned int)fun1((unsigned __int64)YouWouldChk::chk1(void)::JC, (__int64)&v4, a3) == 0;
}
flag2要从附件中读取秘钥来解码字符串,在fun1处copy下来就行了
__asm { endbr64 }
key = a3; // 神必字符串
v25 = __readfsqword(0x28u);
v17 = 'txt.tt';
v18 = 0LL;
v19 = 0LL;
v20 = 0LL;
v21 = 0LL;
v22 = 0LL;
v23 = 0LL;
v24 = 0LL;
v6 = YouWouldChk::readStrFromFile(this, (char *)&v17, (char *)&v12, (__int64)&key);
YouWouldChk::deAes(this, (char *)&v12, a2, v6, (__int64)&key, a5, a6);//aes解密
v13 = 0LL;
v14 = 0LL;
v15 = 0LL;
v16 = 0LL;
sub_4010D0((unsigned __int64)&v12, (signed __int64)&v13, (unsigned __int64)&v12, a5, a6);
std::operator<<<std::char_traits<char>>(&std::cout, "Richard steals some:", v7);
std::operator>><char,std::char_traits<char>>(&std::cin, YouWouldChk::deAesFileAndMore(char *)::RH);
i_1 = 0;
for ( i = 0; *((_BYTE *)&v12 + i); ++i )
{
if ( *((_BYTE *)&key + i - 144) != 'f' )
{
v8 = i_1++;
*((_BYTE *)&key + v8 - 144) = *((_BYTE *)&key + i - 144);
}
}
*((_BYTE *)&key + i_1 - 144) = 0;
return (unsigned int)fun1((unsigned __int64)&v12, (__int64)YouWouldChk::deAesFileAndMore(char *)::RH, a4) == 0;
和flag1一样fun1处复制下来
然后拼到一起
c92bb6a5a6c3009124566d882d4bc7ee
简单地图,不像上个月有多重路径搞得很迷惑
动调载入地图复制出来,稍微处理一下
X X X X X #
X X X X
X X X X X
X X X
X X X X
X X X X
X X
X X X X
md5(jkkjjhjjkjjkkkuukukkuuhhhuukkkk )
for ( i = 31; i_1 < i; --i )
{
if ( (flag[i] ^ flag[i_1]) != *(&v59 + i_1) )
{
f("No_need_to_scare");
return 0;
}
if ( (flag[i] & flag[i_1]) != *(&v43 + i_1) )
{
f("No_need_to_scare");
return 0;
}
if ( (flag[i_1] & 0xF) != *(&v11 + i_1) || (flag[i] & 0xF) != *(&v11 + i) )
{
f("No_need_to_scare");
return 0;
}
++i_1;
}
根据以上判断条件我们可以得到81个符合条件的flag
Nep{mYrclU_a^dOmaxooisonotofree}
Nep{mYrclU_a^d_mahooisonotofree}
Nep{mYrclU_a^domaXooisonotofree}
Nep{mYrclU_andOmaxo_isonotofree}
Nep{mYrclU_and_maho_isonotofree}
Nep{mYrclU_andomaXo_isonotofree}
Nep{mYrclU_a~dOmaxoOisonotofree}
Nep{mYrclU_a~d_mahoOisonotofree}
Nep{mYrclU_a~domaXoOisonotofree}
Nep{mYrcle_a^dOmaxoois_notofree}
Nep{mYrcle_a^d_mahoois_notofree}
Nep{mYrcle_a^domaXoois_notofree}
Nep{mYrcle_andOmaxo_is_notofree}
Nep{mYrcle_and_maho_is_notofree}
Nep{mYrcle_andomaXo_is_notofree}
Nep{mYrcle_a~dOmaxoOis_notofree}
Nep{mYrcle_a~d_mahoOis_notofree}
Nep{mYrcle_a~domaXoOis_notofree}
Nep{mYrclu_a^dOmaxooisOnotofree}
Nep{mYrclu_a^d_mahooisOnotofree}
Nep{mYrclu_a^domaXooisOnotofree}
Nep{mYrclu_andOmaxo_isOnotofree}
Nep{mYrclu_and_maho_isOnotofree}
Nep{mYrclu_andomaXo_isOnotofree}
Nep{mYrclu_a~dOmaxoOisOnotofree}
Nep{mYrclu_a~d_mahoOisOnotofree}
Nep{mYrclu_a~domaXoOisOnotofree}
Nep{mirclU_a^dOmaxooisonot_free}
Nep{mirclU_a^d_mahooisonot_free}
Nep{mirclU_a^domaXooisonot_free}
Nep{mirclU_andOmaxo_isonot_free}
Nep{mirclU_and_maho_isonot_free}
Nep{mirclU_andomaXo_isonot_free}
Nep{mirclU_a~dOmaxoOisonot_free}
Nep{mirclU_a~d_mahoOisonot_free}
Nep{mirclU_a~domaXoOisonot_free}
Nep{mircle_a^dOmaxoois_not_free}
Nep{mircle_a^d_mahoois_not_free}
Nep{mircle_a^domaXoois_not_free}
Nep{mircle_andOmaxo_is_not_free}
Nep{mircle_and_maho_is_not_free}
Nep{mircle_andomaXo_is_not_free}
Nep{mircle_a~dOmaxoOis_not_free}
Nep{mircle_a~d_mahoOis_not_free}
Nep{mircle_a~domaXoOis_not_free}
Nep{mirclu_a^dOmaxooisOnot_free}
Nep{mirclu_a^d_mahooisOnot_free}
Nep{mirclu_a^domaXooisOnot_free}
Nep{mirclu_andOmaxo_isOnot_free}
Nep{mirclu_and_maho_isOnot_free}
Nep{mirclu_andomaXo_isOnot_free}
Nep{mirclu_a~dOmaxoOisOnot_free}
Nep{mirclu_a~d_mahoOisOnot_free}
Nep{mirclu_a~domaXoOisOnot_free}
Nep{myrclU_a^dOmaxooisonotOfree}
Nep{myrclU_a^d_mahooisonotOfree}
Nep{myrclU_a^domaXooisonotOfree}
Nep{myrclU_andOmaxo_isonotOfree}
Nep{myrclU_and_maho_isonotOfree}
Nep{myrclU_andomaXo_isonotOfree}
Nep{myrclU_a~dOmaxoOisonotOfree}
Nep{myrclU_a~d_mahoOisonotOfree}
Nep{myrclU_a~domaXoOisonotOfree}
Nep{myrcle_a^dOmaxoois_notOfree}
Nep{myrcle_a^d_mahoois_notOfree}
Nep{myrcle_a^domaXoois_notOfree}
Nep{myrcle_andOmaxo_is_notOfree}
Nep{myrcle_and_maho_is_notOfree}
Nep{myrcle_andomaXo_is_notOfree}
Nep{myrcle_a~dOmaxoOis_notOfree}
Nep{myrcle_a~d_mahoOis_notOfree}
Nep{myrcle_a~domaXoOis_notOfree}
Nep{myrclu_a^dOmaxooisOnotOfree}
Nep{myrclu_a^d_mahooisOnotOfree}
Nep{myrclu_a^domaXooisOnotOfree}
Nep{myrclu_andOmaxo_isOnotOfree}
Nep{myrclu_and_maho_isOnotOfree}
Nep{myrclu_andomaXo_isOnotOfree}
Nep{myrclu_a~dOmaxoOisOnotOfree}
Nep{myrclu_a~d_mahoOisOnotOfree}
Nep{myrclu_a~domaXoOisOnotOfree}
但是根据常识可以找到Nep{mircle_and_maho_is_not_free}
之后该flag参与一段smc,众所周知单层smc和没有是一样的
但是这个题后面出现了奇怪的东西
v2 = 37;
v3 = 110;
v4 = 49;
v5 = 19;
v6 = 47;
v7 = 40;
v8 = 32;
v9 = 60;
v10 = 53;
v11 = 52;
v12 = 48;
v13 = 109;
v14 = 59;
v15 = 54;
v16 = 7;
v17 = 60;
v18 = 56;
v19 = 127;
v20 = 93;
v21 = 84;
v22 = 40;
v23 = 30;
v24 = 26;
v25 = 47;
v26 = 59;
v27 = 43;
v28 = 85;
v29 = 54;
v30 = 73;
v31 = 109;
v32 = 102;
v33 = 126;
v34 = 0;
v35 = 1601399123;
v36 = 1818588528;
v37 = 1834967404;
v0 = __inbyte(0x66u);
v38 = 8545;
v39 = BYTE2(dword_405150);
v40 = 0i64;
v41 = 0;
v42 = 0;
for ( i = 0; i < strlen(flag); ++i )
*((_BYTE *)&v43 + i - 73) = *((_BYTE *)&v43 + (signed int)i % 18 - 37) ^ *((_BYTE *)&v43 + 4 * i - 205) ^ flag[i];
后面并没有对flag进行判断,直接把flag跑出来了。。。。
.scode:00403219 loc_403219:
.scode:00403219 0EC xor ecx, eax
.scode:0040321B 0EC mov edx, [ebp-0D8h]
.scode:00403221 0EC mov [ebp+edx-4Ch], cl <---
.scode:00403225 1D8 jmp loc_403186
Stack[0000633C]:0019FE58 a8b272473500a45 db '8b272473500a451286ab225413f1debd',0
8b272473500a451286ab225413f1debd
看起来花里胡哨的rc4
cpp程序直接对着伪代码调试也可以得到比较好的效果
v16 = __readfsqword(0x28u);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&FLAG, a2);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&a3, a2, v2);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(&v13, a2, v3);
init_key((__int64)v15);//秘钥生成
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(&a3, v15);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v15);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length();
if ( v4 != 37 )
{
a1 = 0;
v5 = 0;
}
else
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::basic_string(v15, &FLAG);
v6 = chk2((__int64)v15); // 判断格式
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(v15);
if ( v6 )
{
qmemcpy(v15, &unk_55AD074D7DC0, sizeof(v15));
encode((__int64)&FLAG_1, (__int64)&FLAG, (__int64)&a3);//RC4加密
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator=(&v13, &FLAG_1);
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::~basic_string(&FLAG_1);
for ( i = 0; ; ++i )
{
std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::length();
if ( i >= v7 )
break;
if ( *(char *)std::__cxx11::basic_string<char,std::char_traits<char>,std::allocator<char>>::operator[](&v13, i) != v15[i] )
{
a1 = 0;
{
__int64 result; // rax
unsigned int v5; // eax
unsigned int v6; // [rsp+1Ch] [rbp-Ch]
int v7; // [rsp+20h] [rbp-8h]
unsigned int i; // [rsp+24h] [rbp-4h]
rc4_init(a3, a4);
v6 = 0;
v7 = 0;
for ( i = 0; ; ++i )
{
result = i;
if ( a2 <= i )
break;
v6 = (unsigned __int8)(((unsigned int)((signed int)(v6 + 1) >> 31) >> 24) + v6 + 1)
- ((unsigned int)((signed int)(v6 + 1) >> 31) >> 24);
v5 = (unsigned int)((v7 + tab[v6]) >> 31) >> 24;
v7 = (unsigned __int8)(v5 + v7 + tab[v6]) - v5;
exchange((char *)&tab[v6], (char *)&tab[v7]);
*(_BYTE *)((signed int)i + a1) ^= tab[(unsigned __int8)(tab[v6] + tab[v7])];
}
return result;
}
很明显的rc4,对着异或点看数据就行了
l = [0x80, 0x59, 0x23, 0x35, 0x2b, 0x4, 0x8f, 0x1e, 0x55, 0x26, 0x32, 0xe8, 0x50, 0x57, 0x81, 0xa, 0xc4, 0x94, 0x25,
0xdc, 0x84, 0x69, 0x76, 0xe6, 0x54, 0xb, 0x6e, 0xf3, 0x53, 0x31, 0x62, 0x49, 0xc, 0xff, 0xff, 0xfa, 0x22, 0x0]
flag = [0x4e, 0x65, 0x70, 0x7b, 0x31, 0x32, 0x33, 0x41, 0x42, 0x43, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x7d, 0x0]
encode = [0x80, 0x59, 0x23, 0x35, 0x22, 0x73, 0x8d, 0x1a, 0x51, 0x5d, 0x30, 0xe8, 0x57, 0x26, 0xf6, 0x7, 0xc6, 0x92,
0x5e, 0xdc, 0x83, 0x1f, 0x76, 0x92, 0x25, 0xf, 0x65, 0xfb, 0x2e, 0x4d, 0x6b, 0x45, 0x3, 0x87, 0xe9, 0x9f, 0x22, 0x0]
for i in range(37):
print(chr(encode[i]^(l[i]^flag[i])),end='')
Nep{8E1EF8215BC841CAE5D17CCA77EAA7F4}
把很可疑的字符串拿出来,试了试是不行的,又觉得a很可疑,把a全去掉就可以正常解base64了…
YamaNalaZaTacaxaZaDahajaYamaIa0aNaDaUa3aYajaUawaNaWaNajaMajaUawaNWI3M2NhMGM=
>>
YmNlZTcxZDhjYmI0NDU3YjUwNWNjMjUwNWI3M2NhMGM=
>>
bcee71d8cbb4457b505cc2505b73ca0c