BUUCTF_[V&N2020 公开赛]strangeCpp
照例打开IDA,翻了翻函数没有找到main函数,那就shift + F12 查找字符串,看看有没什么敏感字符,如图:
点进去查看字符串的交叉引用(按 x ),如图:
找到sub_140013AA0用F5,如图:
__int64 __fastcall sub_140013AA0(__int64 a1, __int64 a2, __int64 *a3)
{
char *v3; // rdi
signed __int64 i; // rcx
__int64 v5; // rax
__int64 v6; // rax
__int64 v7; // rax
__int64 v8; // rax
char v10; // [rsp+0h] [rbp-20h]
struct _SYSTEM_INFO SystemInfo; // [rsp+28h] [rbp+8h]
__int64 *j; // [rsp+78h] [rbp+58h]
__int64 v13; // [rsp+98h] [rbp+78h]
__int64 *v14; // [rsp+1A0h] [rbp+180h]
v14 = a3;
v3 = &v10;
for ( i = 94i64; i; --i )
{
*(_DWORD *)v3 = -858993460;
v3 += 4;
}
sub_1400110AA((__int64)&unk_140027033);
GetSystemInfo(&SystemInfo);
putchar(byte_140021004);
putchar(byte_140021005);
putchar(byte_140021006);
putchar(byte_140021007);
putchar(byte_140021019);
putchar(byte_14002101A);
putchar(byte_140021005);
putchar(10);
puts("Let me have a look at your computer...");
for ( j = v14; *j; ++j )
{
v13 = *j;
sub_140011226((__int64)"%s\n", v13);
}
std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
dword_140021190 = SystemInfo.dwNumberOfProcessors;
sub_140011226((__int64)"now system cpu num is %d\n", SystemInfo.dwNumberOfProcessors);
if ( dword_140021190 < 8 )
{
puts("Are you in VM?");
_exit(0);
}
if ( GetUserNameA(Str1, &pcbBuffer) )
{
v5 = sub_140011172(std::cout, "this is useful");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v5, sub_140011127);
}
v6 = std::basic_ostream<char,std::char_traits<char>>::operator<<(std::cout, sub_140011127);
v7 = sub_140011172(v6, "ok,I am checking...");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v7, sub_140011127);
if ( !j_strcmp(Str1, "cxx") )
{
v8 = sub_140011172(std::cout, "flag{where_is_my_true_flag?}");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v8, sub_140011127);
_exit(0);
}
system("pause");
sub_1400113E3((__int64)&v10, (__int64)&unk_14001DE50);
return 0i64;
}
好复杂,不过点进各种字符串查看交叉引用都没有其他的交叉引用,唯有下图有点东西:
点进去看,很奇怪的发现中间那段有点不太一样.
按x查看一下交叉引用.
来到sub_140013580用F5大法,发现关键函数!!!
红框的语句为关键函数,进入sub_140011384看看.
到现在为止已经将整个程序的逻辑看完了,现在来理一下逻辑sub_140011384 把 dword_140021190 当成实参传进去,也就是说a1就是dword_140021190,接着 a1 又给了 v8 ,接下来v8进行移位操作等于 v7 , v7 又乘与 291,接下来就返回 result ,也就是说 dword_140021190 -> a1 ->v8 -> v7 ->result,接下来要求result = 607052314 ,dword_140021190 <= 14549743,进入 if 后将 dword_140021190 与 byte_140021008 异或,那么现在只要爆破出 dword_140021190 的值,再进行异或就结束了.
分析完了,开始写python脚本
str = [0x26,0x2C,0x21,0x27,0x3B,0x0D,0x04,0x75,0x68,0x34,0x28,0x25,0x0E,0x35,0x2D,0x69,0x3D]
result = 607052314
flag = ''
num = 0
for i in range(14549743):
v7 = (i << 8) ^ (i >> 12)
v7 *= 291
v7 = v7 & 0xFFFFFFFF
if v7 == result:
num = i
print(i)
break
for i in str:
flag += chr((num ^ i) &0xFF)
print(flag)
答案还要对爆破的值进行MD5加密,那直接上脚本:
import hashlib
def getMd5(str):
#获取一个MD5的加密算法对象
md5_value = hashlib.md5()
#得到MD5消息摘要
md5_value.update(str.encode('utf-8'))
#以16进制返回消息
print(md5_value.hexdigest())
if __name__=="__main__":
getMd5('123456')
至此,程序分析结束!!!
小结:
①再亿次提醒自己看字符串要再Hew View里面看,在 IDA View真的很容易漏!!!
②python需要对字符串进行截断 unsigned int 就是4个字节,不截断就如下图一样,没有爆破出来.