逆向攻防世界CTF系列47-crazy
逆向攻防世界CTF系列47-crazy
64位无壳
丢入IDA并远程调试,随便输入,发现要32位长度,也跟踪到几个函数
校验函数:
判断长度和简单处理逻辑
主函数:
到这逻辑理顺了,其实这题的难点主要在眼花缭乱的C++代码
会头看这,应该是把输入赋值给a1+16和a1+48,然后把327a6c4304ad5938eaf0efb6cc3e53dc给了a1+80
unsigned __int64 __fastcall HighTemplar::HighTemplar(DarkTemplar *a1, __int64 a2)
{
char v3; // [rsp+17h] [rbp-19h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-18h]
v4 = __readfsqword(0x28u);
DarkTemplar::DarkTemplar(a1);
*(_QWORD *)a1 = &off_401EA0;
*((_DWORD *)a1 + 3) = 0;
std::string::basic_string((__int64)a1 + 16, a2);
std::string::basic_string((__int64)a1 + 48, a2);
std::allocator<char>::allocator(&v3);
std::string::basic_string((char *)a1 + 80, "327a6c4304ad5938eaf0efb6cc3e53dc", &v3);
std::allocator<char>::~allocator(&v3);
return __readfsqword(0x28u) ^ v4;
}
要逆向,从后面再看:
__int64 __fastcall HighTemplar::getSerial(HighTemplar *this){
for ( i = 0; (int)i < (unsigned __int64)std::string::length((char *)this + 16); ++i){
// 这里我猜是this+80处和变过的this比,然后,下面两段分别把它取出来了,然后作比较
v1 = *(_BYTE *)std::string::operator[]((char *)this + 80, (int)i);
if ( v1 != *(_BYTE *)std::string::operator[]((char *)this + 16, (int)i)){
v4 = std::operator<<<std::char_traits<char>>(&std::cout, "You did not pass ");
v5 = std::ostream::operator<<(v4, i);
std::ostream::operator<<(v5, &std::endl<char,std::char_traits<char>>);
*((_DWORD *)this + 3) = 1;
return *((unsigned int *)this + 3);
}
v2 = std::operator<<<std::char_traits<char>>(&std::cout, "Pass ");
v3 = std::ostream::operator<<(v2, i);
std::ostream::operator<<(v3, &std::endl<char,std::char_traits<char>>);
}
return *((unsigned int *)this + 3);
}
enc:327a6c4304ad5938eaf0efb6cc3e53dc
看calctue:
bool __fastcall HighTemplar::calculate(HighTemplar *this){
if ( std::string::length((char *)this + 16) != 32 ){
v1 = std::operator<<<std::char_traits<char>>(&std::cout, "Too short or too long");
std::ostream::operator<<(v1, &std::endl<char,std::char_traits<char>>);
exit(-1);
}
for ( i = 0; i <= (unsigned __int64)std::string::length((char *)this + 16); ++i ){
v2 = (_BYTE *)std::string::operator[]((char *)this + 16, i);
*v2 = (*(_BYTE *)std::string::operator[]((char *)this + 16, i) ^ 0x50) + 23;
}
for ( j = 0; ; ++j ) {
result = j <= (unsigned __int64)std::string::length((char *)this + 16);
if ( !result ) break;
v4 = (_BYTE *)std::string::operator[]((char *)this + 16, j);
*v4 = (*(_BYTE *)std::string::operator[]((char *)this + 16, j) ^ 0x13) + 11;
}
return result;
}
首先满足32长度,然后对每一位^0x50,再加23
然后 ^ 0x13 + 11
解密代码:
enc = '327a6c4304ad5938eaf0efb6cc3e53dc'
flag1 = ''
flag2 = ''
for i in range(len(enc)):
flag1 += chr(ord(enc[i]) - 11 ^ 0x13)
for i in range(len(enc)):
flag2 += chr(ord(flag1[i]) - 23 ^ 0x50)
print(flag2)
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Matriy
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果