childre 考点:C++名字修饰,二叉树

  1. 定位到关键函数并不困难
signed __int64 sub_140001610()
{
  signed __int64 v0; // rax
  _QWORD *v1; // rax
  const CHAR *v2; // r11
  __int64 v3; // r10
  __int64 v4; // r9
  const CHAR *v5; // r10
  signed __int64 v6; // rcx
  __int64 v7; // rax
  signed __int64 result; // rax
  unsigned int v9; // ecx
  __int64 v10; // r9
  int v11; // er10
  __int64 v12; // r8
  __int128 input; // [rsp+20h] [rbp-38h]
  __int128 v14; // [rsp+30h] [rbp-28h]

  input = 0i64;
  v14 = 0i64;
  sub_140001080("%s", &input);
  v0 = -1i64;
  do
    ++v0;
  while ( *(&input + v0) );
  if ( v0 != 31 )
  {
    while ( 1 )
      Sleep(1000u);
  }
  v1 = sub_140001280(&input);                   // 二叉树保存
  v2 = name;
  if ( v1 )                                     // 递归算法
  {
    sub_1400015C0(v1[1]);
    sub_1400015C0(*(v3 + 16));
    v4 = dword_1400057E0;
    v2[v4] = *v5;
    dword_1400057E0 = v4 + 1;
  }
  UnDecorateSymbolName(v2, outputString, 0x100u, 0);//
  v6 = -1i64;
  do
    ++v6;
  while ( outputString[v6] );
  if ( v6 == 62 )
  {
    v9 = 0;
    v10 = 0i64;
    do
    {
      v11 = outputString[v10];                  // private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)
      v12 = v11 % 23;
      if ( str1[v12] != *(v10 + 0x140003478i64) )// str2 (_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&
        _exit(v9);
      if ( str1[v11 / 23] != *(v10 + 0x140003438i64) )// str3 
                                                // 55565653255552225565565555243466334653663544426565555525555222
        _exit(v9 * v9);
      ++v9;
      ++v10;
    }
    while ( v9 < 62 );
    sub_140001020("flag{MD5(your input)}\n", v11 / 23, v12, v10);
    result = 0i64;
  }
  else
  {
    v7 = sub_1400018A0(std::cout);
    std::basic_ostream<char,std::char_traits<char>>::operator<<(v7, sub_140001A60);
    result = 0xFFFFFFFFi64;
  }
  return result;
}

输出长度是32,然后最后处理之后的是62位置。

 

一开始我想正向去处理,但是中间的二叉树保存和中序遍历复现实在有点难度,那就从后面往前。

可以解出outstring,为private: char * __thiscall R0Pxx::My_Aut0_PWN(unsigned char *)

str1=r'1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;'+chr(0x27)
str2=r'(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&'
str3=r'55565653255552225565565555243466334653663544426565555525555222'

outstring=""

for i in range(62):
    a=str1.find(str2[i]) 
    b=str1.find(str3[i])
    outstring+=chr(b*23+a)
print(outstring)   

outstring是函数 UnDecorateSymbolName(v2, outputString, 0x100u, 0);// ?处理结果,这是一个C++的名字修饰函数,这一块有两个方法处理得到v2:

(参考前辈文章)

 方法一:

参考资料1
可以知道第二个参数为未修饰的名字,第三个参数为长度,第四个参数为0表示完全修饰,第一个参数为输出地址

参考资料2

c++函数名的修饰更为复杂,提供的信息也更为丰富。
无论 __cdecl,__fastcall还是__stdcall调用方式,函数修饰都是以一个“?”开始,后面紧跟函数的名字。再后面是参数表的开始标识和依照参数类型代号拼出的参数表。

v2 = ?My_Aut0_PWN

对于C++的类成员函数(其调用方式是thiscall),函数的名字修饰与非成员的C++函数稍有不同,首先就是在函数名字和参数表之间插入以“@”字 符引导的类名。

v2 = ?My_Aut0_PWN@R0Pxx

其次是参数表的开始标识不同,公有(public)成员函数的标识是“@@QAE”,保护(protected)成员函数的标识是 “@@IAE”,私有(private)成员函数的标识是“@@AAE”,假设函数声明使用了constkeyword,则对应的标识应分别为“@@QBE”,“@@IBE”和“@@ABE”。

因为函数为private,私有成员
所以v2 =?My_Aut0_PWN@R0Pxx@@AAE
后面就是添加参数了,先加入函数返回值参数,函数的返回值类型为char *

参数表的拼写代号如下:
X–void
D–char
E–unsigned char
F–short
H–int
I–unsigned int
J–long
K–unsigned long(DWORD)
M–float
N–double
_N–bool
U–struct

指针的方式有些特别。用PA表示指针,用PB表示const类型的指针。

char *也就是PAD
所以v2 = ?My_Aut0_PWN@R0Pxx@@AAEPAD
然后是参数的类型unsigned char *,也就是PAE
所以v2 = ?My_Aut0_PWN@R0Pxx@@AAEPADPAE

参数表后以“@Z”标识整个名字的结束。假设该函数无参数,则以“Z”标识结束。

所以最终v2 = ?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z

方法二:

#include<iostream>
using namespace std;

class ROPxx {
public:
    ROPxx(){
        unsigned char a;
        My_Aut0_PWN(&a);
    }

private:
    char My_Aut0_PWN(unsigned char*) {
        printf("%s", __FUNCDNAME__);
        return '0';
    }
};
int main() {
    new ROPxx();
    getchar();
    return 0;
}

 

v2是变换之后的字符串,获得输入字符串还需要克服二叉树保存那块,也就是知道这个二叉树保存的方式和 读出(前序或者后序)方式,好在动态调试可以获得替换的索引表:

0x50, 0x51, 0x48, 0x52, 0x53, 0x49, 0x44, 0x54, 0x55, 0x4a, 0x56, 0x57, 0x4b, 0x45, 0x42, 0x58, 0x59, 0x4c, 0x5a, 0x5b, 0x4d, 0x46, 0x5c, 0x5d, 0x4e, 0x5e, 0x5f, 0x4f, 0x47, 0x43, 65

2.keygen:

for i in range(62):
    a=str1.find(str2[i]) 
    b=str1.find(str3[i])
    outstring+=chr(b*23+a)
print(outstring)
str1 = '?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'
result = [''] * 31
index3 = [15, 16, 7, 17, 18, 8, 3, 19, 20, 9, 21, 22, 10, 4, 1, 23, 24, 11, 25, 26, 12, 5, 27, 28, 13, 29, 30, 14, 6, 2, 0]
print(len(str1))
for i in range(len(str1)):
    result[index3[i]] += str1[i]
ss = ''.join(i for i in result)
print(ss)

 

原文链接: https://www.cnblogs.com/jentleTao/p/12796542.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    childre 考点:C++名字修饰,二叉树

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/344870

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年3月2日 上午2:56
下一篇 2023年3月2日 上午2:56

相关推荐