查看信息
分析代码
int __cdecl main(int argc, const char **argv, const char **envp)
{
__int64 v3; // rax
_QWORD *v4; // rax
const CHAR *v5; // r11
__int64 v6; // r10
int v7; // er9
const CHAR *v8; // r10
__int64 v9; // rcx
__int64 v10; // rax
unsigned int v12; // ecx
__int64 v13; // r9
__int128 input[2]; // [rsp+20h] [rbp-38h] BYREF
memset(input, 0, sizeof(input));
sub_7FF714171080("%s", (const char *)input);
v3 = -1i64;
do
++v3;
while ( *((_BYTE *)input + v3) );
if ( v3 != 0x1F ) // 输入字符串长度为32
{
while ( 1 )
Sleep(0x3E8u);
}
v4 = sub_7FF714171280(input); // 加密(打乱顺序)
v5 = name;
if ( v4 )
{
sub_7FF7141715C0((unsigned __int8 *)v4[1]); //打乱顺序
sub_7FF7141715C0(*(unsigned __int8 **)(v6 + 16));
v7 = dword_7FF7141757E0;
v5[dword_7FF7141757E0] = *v8;
dword_7FF7141757E0 = v7 + 1;
}
UnDecorateSymbolName(v5, outputString, 0x100u, 0);
v9 = -1i64;
do
++v9;
while ( outputString[v9] );
if ( v9 == 0x3E )
{
v12 = 0;
v13 = 0i64;
do //比较结果
{
if ( a1234567890Qwer[outputString[v13] % 23] != a46200860044218[v13] )
_exit(v12);
if ( a1234567890Qwer[outputString[v13] / 23] != a55565653255552[v13] )
_exit(v12 * v12);
++v12;
++v13;
}
while ( v12 < 62 );
sub_7FF714171020("flag{MD5(your input)}\n");
return 0;
}
else
{
v10 = sub_7FF7141718A0(std::cout);
std::ostream::operator<<(v10, sub_7FF714171A60);
return -1;
}
}
可以先写脚本将outputstring中的值给求出来
a123 = [0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30,
0x2D, 0x3D, 0x21, 0x40, 0x23, 0x24, 0x25, 0x5E, 0x26, 0x2A,
0x28, 0x29, 0x5F, 0x2B, 0x71, 0x77, 0x65, 0x72, 0x74, 0x79,
0x75, 0x69, 0x6F, 0x70, 0x5B, 0x5D, 0x51, 0x57, 0x45, 0x52,
0x54, 0x59, 0x55, 0x49, 0x4F, 0x50, 0x7B, 0x7D, 0x61, 0x73,
0x64, 0x66, 0x67, 0x68, 0x6A, 0x6B, 0x6C, 0x3B, 0x27, 0x41,
0x53, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, 0x4C, 0x3A, 0x22,
0x5A, 0x58, 0x43, 0x56, 0x42, 0x4E, 0x4D, 0x3C, 0x3E, 0x3F,
0x7A, 0x78, 0x63, 0x76, 0x62, 0x6E, 0x6D, 0x2C, 0x2E, 0x2F,
]
a462 = "(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&"
a555 = "55565653255552225565565555243466334653663544426565555525555222"
outputString = ""
for i in range(62):
for j in range(33,128):
if(a123[j % 23] == ord(a462[i]) and a123[j // 23] == ord(a555[i]) ):
outputString += chr(j)
break
else:
continue
print(outputString)
# 结果
private:char*__thiscallR0Pxx::My_Aut0_PWN(unsignedchar*)
然后就是这个函数了,可以参考unDecorateSymbolName 函数 以及 c, c++函数名编译符号修饰符说明
UnDecorateSymbolName(v5, outputString, 0x100u, 0);
思路可以参考这个大佬的博客
C++的类成员函数(其调用方式是thiscall)。函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和參数表之间插入以“@”字 符引导的类名
简单来说就是以 @ 来分割,对应关系如下
? My_Aut0_PWN @R0Pxx @@AAE PA D PA E @Z
以?开始 函数名 类名 私有(private)成员函数的标识 返回指针 char拼写代号 参数指针 unsigned拼写代号 结束
合起来就是 ?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z
接下来分析这段代码
if ( v4 )
{
sub_7FF7141715C0((unsigned __int8 *)v4[1]);
sub_7FF7141715C0(*(unsigned __int8 **)(v6 + 16));
v7 = dword_7FF7141757E0;
v5[dword_7FF7141757E0] = *v8;
dword_7FF7141757E0 = v7 + 1;
}
感觉像个二叉树遍历,试了下还原二叉树但是咋搞都不对
__int64 __fastcall sub_7FF7141715C0(unsigned __int8 *a1)
{
int v2; // er8
__int64 result; // rax
if ( a1 )
{
sub_7FF7141715C0(*((_QWORD *)a1 + 1));
sub_7FF7141715C0(*((_QWORD *)a1 + 2));
v2 = dword_7FF7141757E0;
result = *a1;
name[dword_7FF7141757E0] = result;
dword_7FF7141757E0 = v2 + 1;
}
return result;
}
参考这个大佬的博客
直接在输入的时候使用 “ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_” 刚好对应65~95
得出结果为 “PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA”,减去 ‘A’ 刚好对应每个数的下标
写出脚本
from hashlib import md5
index = "PQHRSIDTUJVWKEBXYLZ[MF\]N^_OGCA"
s = "?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z"
flag_1 = [0] * 31
for i in range(31):
flag_1[ord(index[i]) - ord('A')] = s[i]
flag = ""
for i in flag_1:
flag = flag + str(i)
print(flag)
print(md5(flag.encode('utf-8')).hexdigest())
得到结果为
Z0@tRAEyuP@xAAA?M_A0_WNPx@@EPDP
63b148e750fed3a33419168ac58083f5
flag{63b148e750fed3a33419168ac58083f5}