zoukankan      html  css  js  c++  java
  • 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)}
    ", 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)
  • 相关阅读:
    mysqldump 逻辑备份和物理备份
    mysql备份
    MySQL日志
    mysql 查询缓存
    Error: xz compression not available的解决办法
    rsync + crontab + expect 快速搭建同步
    同步文件,不需要密码
    logstash 值得收藏的
    MySQL5.7主从,单slave多master
    微信代扣签名
  • 原文地址:https://www.cnblogs.com/jentleTao/p/12796542.html
Copyright © 2011-2022 走看看