• 2019看雪CTF 晋级赛Q2第四题wp


    上次参加2019看雪CTF 晋级赛Q2卡在了这道题上,虽然逆出算法,但是方程不会解,哈哈哈哈,果然数学知识很重要呀,现在记录一下。

    首先根据关键信息,根据错误提示字符串定位到这里:

     1 int __thiscall guanjian_401EA0(CWnd *this)
     2 {
     3   CWnd *v1; // esi
     4   int index; // eax
     5   WCHAR String; // [esp+Ch] [ebp-310h]
     6   char v5; // [esp+Eh] [ebp-30Eh]
     7   char ptr; // [esp+20Ch] [ebp-110h]
     8   char v7; // [esp+20Dh] [ebp-10Fh]
     9   DWORD v8; // [esp+30Ch] [ebp-10h]
    10   CWnd *v9; // [esp+310h] [ebp-Ch]
    11   int v10; // [esp+314h] [ebp-8h]
    12   DWORD flOldProtect; // [esp+318h] [ebp-4h]
    13 
    14   v1 = this;
    15   v9 = this;
    16   String = 0;
    17   memset(&v5, 0, 0x1FEu);
    18   ptr = 0;
    19   memset(&v7, 0, 0xFFu);
    20   CWnd::GetDlgItemTextW(v1, 1000, &String, 20);
    21   if ( wcslen(&String) == 16 )
    22   {
    23     index = 0;
    24     while ( !(*(&String + index) & 0xFF00) )
    25     {
    26       *(&ptr + index) = *((_BYTE *)&String + 2 * index);
    27       if ( ++index >= 16 )
    28       {
    29         v8 = 64;
    30         flOldProtect = 0;
    31         VirtualProtect(sub_9D10E0, 0xD17u, 0x40u, &flOldProtect);// BOOL VirtualProtect(  
    32                                                 //   LPVOID lpAddress,  
    33                                                 //   DWORD dwSize,  
    34                                                 //   DWORD flNewProtect,  
    35                                                 //   PDWORD lpflOldProtect 
    36                                                 // lpAddress,要改变属性的内存起始地址。
    37                                                 // 
    38                                                 // dwSize,要改变属性的内存区域大小。
    39                                                 // 
    40                                                 // flNewProtect,内存新的属性类型,设置为PAGE_EXECUTE_READWRITE(0x40)时该内存页为可读可写可执行。
    41                                                 // 
    42                                                 // pflOldProtect,内存原始属性类型保存地址。
    43                                                 // 
    44                                                 // 
    45         GetLastError();
    46         qmemcpy(sub_9D10E0, byte_B347B8, 0x330u);
    47         VirtualProtect(sub_9D10E0, 0xD17u, flOldProtect, &v8);
    48         if ( !GetLastError() )
    49         {
    50           v10 = 0;
    51           v10 = sub_9D10E0();
    52           if ( v10 == 1 )
    53             return CWnd::MessageBoxW(v9, L"Congratulations! You are right!", 0, 0);
    54         }
    55         v1 = v9;
    56         return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
    57       }
    58     }
    59   }
    60   return CWnd::MessageBoxW(v1, L"Wrong!", 0, 0);
    61 }
    注意到运行时先修改sub_9D10E0()代码段,然后再运行sub_9D10E0(),我们动态调试,dump出修改完成的sub_9D10E0()代码段
      1 int __cdecl sub_9D10E0(char *input)
      2 {
      3   signed int i; // eax
      4   char v2; // cl
      5   signed int v3; // ecx
      6   signed int v4; // eax
      7   signed int low_index; // eax
      8   signed int j; // esi
      9   signed int k; // ecx
     10   __int16 v8; // dx
     11   char *buffer_ptr_; // edi
     12   __int16 v10; // ax
     13   signed int temp_1; // eax
     14   signed int m_1; // ecx
     15   unsigned __int16 t_3; // bx
     16   signed int j_1; // esi
     17   signed int k_1; // ecx
     18   __int16 v16; // dx
     19   char *buffer_ptr; // edi
     20   __int16 t_4; // ax
     21   signed int t; // eax
     22   signed int m; // ecx
     23   unsigned __int16 temp; // bx
     24   unsigned int t_1; // eax
     25   signed int i_2; // ecx
     26   unsigned __int16 temp_2; // dx
     27   char f; // dl
     28   signed int i_1; // eax
     29   __int16 t_2; // si
     30   int index; // eax
     31   char s_xor[17]; // [esp+8h] [ebp-90h]
     32   int v31; // [esp+1Ch] [ebp-7Ch]
     33   int v32; // [esp+20h] [ebp-78h]
     34   int v33; // [esp+24h] [ebp-74h]
     35   char x[8]; // [esp+28h] [ebp-70h]
     36   char buffer[16]; // [esp+30h] [ebp-68h]
     37   char y[8]; // [esp+40h] [ebp-58h]
     38   char yy7_result[17]; // [esp+48h] [ebp-50h]
     39   char result[17]; // [esp+5Ch] [ebp-3Ch]
     40   char xx_result[17]; // [esp+70h] [ebp-28h]
     41   char yy_result[17]; // [esp+84h] [ebp-14h]
     42 
     43   s_xor[4] = 0x81u;
     44   s_xor[11] = 0x81u;
     45   i = 0;
     46   s_xor[0] = 0x16;
     47   s_xor[1] = -106;
     48   s_xor[2] = -116;
     49   s_xor[3] = -29;
     50   s_xor[5] = -104;
     51   s_xor[6] = 110;
     52   s_xor[7] = 100;
     53   s_xor[8] = 0x84u;
     54   s_xor[9] = 8;
     55   s_xor[10] = -36;
     56   s_xor[12] = 0xBEu;
     57   s_xor[13] = 77;
     58   s_xor[14] = 72;
     59   s_xor[15] = 79;
     60   *(_DWORD *)&s_xor[16] = 0;
     61   v31 = 0;
     62   v32 = 0;
     63   v33 = 0;
     64   *(_DWORD *)x = 0;
     65   *(_DWORD *)&x[4] = 0;
     66   *(_DWORD *)y = 0;
     67   *(_DWORD *)&y[4] = 0;
     68   do
     69   {                                             // 先将输入分成两部分,记为x,y,然后进行异或操作,
     70     v2 = s_xor[i + 8] ^ input[i + 8];           // 从输入的第9位开始处理,索引8-15
     71                                                 // 异或
     72     x[i] = s_xor[i] ^ s_xor[i + input - s_xor]; // 输入的前8位
     73                                                 // 异或
     74     y[i++] = v2;
     75   }
     76   while ( i < 8 );
     77   *(_DWORD *)s_xor = 0;
     78   *(_DWORD *)xx_result = 0;
     79   *(_DWORD *)&xx_result[4] = 0;
     80   *(_DWORD *)&xx_result[8] = 0;
     81   *(_DWORD *)&xx_result[12] = 0;
     82   xx_result[16] = 0;
     83   *(_DWORD *)yy_result = 0;
     84   *(_DWORD *)&yy_result[4] = 0;
     85   *(_DWORD *)&yy_result[8] = 0;
     86   *(_DWORD *)&yy_result[12] = 0;
     87   yy_result[16] = 0;
     88   *(_DWORD *)yy7_result = 0;
     89   *(_DWORD *)&yy7_result[4] = 0;
     90   *(_DWORD *)&yy7_result[8] = 0;
     91   *(_DWORD *)&yy7_result[12] = 0;
     92   yy7_result[16] = 0;
     93   *(_DWORD *)result = 0;
     94   *(_DWORD *)&result[4] = 0;
     95   *(_DWORD *)&result[8] = 0;
     96   *(_DWORD *)&result[12] = 0;
     97   result[16] = 0;
     98   *(_DWORD *)&s_xor[4] = 0;
     99   *(_DWORD *)&s_xor[8] = 0;
    100   *(_DWORD *)&s_xor[12] = 0;
    101   s_xor[16] = 0;
    102   v3 = 8;
    103   s_xor[0] = 8;
    104   v4 = 7;
    105   do
    106   {
    107     if ( x[v4] )                                // x[7]!=0
    108       break;
    109     --v3;
    110     --v4;
    111   }
    112   while ( v4 >= 0 );
    113   if ( v3 == 8 )
    114   {
    115     low_index = 7;
    116     do
    117     {
    118       if ( y[low_index] )                       // y[7]!=0
    119         break;
    120       --v3;
    121       --low_index;
    122     }
    123     while ( low_index >= 0 );                   // 输入为16位
    124     if ( v3 == 8 && !(x[7] & 0xF0) )            // 第8位<0x10
    125     {
    126       j = 0;
    127       do
    128       {
    129         *(_DWORD *)buffer = 0;
    130         *(_DWORD *)&buffer[4] = 0;
    131         *(_DWORD *)&buffer[8] = 0;
    132         *(_DWORD *)&buffer[12] = 0;
    133         k = 0;
    134         v8 = (unsigned __int8)x[j];
    135         buffer_ptr_ = &buffer[j];
    136         do
    137         {
    138           v10 = (unsigned __int8)buffer[j + 8] + v8 * (unsigned __int8)x[k];
    139           buffer_ptr_[k] = buffer[j + 8] + v8 * x[k];
    140           ++k;
    141           buffer[j + 8] = HIBYTE(v10);
    142         }
    143         while ( k < 8 );
    144         LOBYTE(temp_1) = 0;
    145         m_1 = 0;
    146         do
    147         {
    148           t_3 = (char)temp_1 + (unsigned __int8)xx_result[m_1 + j] + (unsigned __int8)buffer_ptr_[m_1];
    149           xx_result[m_1++ + j] = t_3;
    150           temp_1 = (signed int)t_3 >> 8;
    151         }
    152         while ( m_1 < 9 );
    153         ++j;                                    // 先按字节乘,再加进位,和手算乘法原理一致
    154       }
    155       while ( j < 8 );                          // 通过两层循环其实是为了计算大数相乘,这里算出x^2
    156       j_1 = 0;
    157       do
    158       {
    159         *(_DWORD *)buffer = 0;
    160         *(_DWORD *)&buffer[4] = 0;
    161         *(_DWORD *)&buffer[8] = 0;
    162         *(_DWORD *)&buffer[12] = 0;
    163         k_1 = 0;
    164         v16 = (unsigned __int8)y[j_1];
    165         buffer_ptr = &buffer[j_1];
    166         do
    167         {
    168           t_4 = (unsigned __int8)buffer[j_1 + 8] + v16 * (unsigned __int8)y[k_1];
    169           buffer_ptr[k_1] = buffer[j_1 + 8] + v16 * y[k_1];
    170           ++k_1;
    171           buffer[j_1 + 8] = HIBYTE(t_4);
    172         }
    173         while ( k_1 < 8 );
    174         LOBYTE(t) = 0;
    175         m = 0;
    176         do
    177         {
    178           temp = (char)t + (unsigned __int8)yy_result[m + j_1] + (unsigned __int8)buffer_ptr[m];
    179           yy_result[m++ + j_1] = temp;
    180           t = (signed int)temp >> 8;
    181         }
    182         while ( m < 9 );
    183         ++j_1;                                  // 这里计算出y^2
    184       }
    185       while ( j_1 < 8 );
    186       LOBYTE(t_1) = yy7_result[16];
    187       i_2 = 0;
    188       do
    189       {                                         // 这里计算7*y^2
    190         temp_2 = (unsigned __int8)t_1 + 7 * (unsigned __int8)yy_result[i_2];
    191         yy7_result[i_2++] = temp_2;
    192         t_1 = (unsigned int)temp_2 >> 8;
    193       }
    194       while ( i_2 < 17 );
    195       yy7_result[16] = HIBYTE(temp_2);
    196       f = 0;
    197       i_1 = 0;
    198       do
    199       {
    200         t_2 = (unsigned __int8)xx_result[i_1] - (unsigned __int8)yy7_result[i_1] - f;
    201         result[i_1] = t_2;
    202         if ( t_2 < 0 )
    203           f = 1;
    204         ++i_1;
    205       }
    206       while ( i_1 < 17 );
    207       if ( !f )
    208       {
    209         index = 0;
    210         while ( result[index] == s_xor[index] ) // 这里相当于验证x^2-7*y^2==8
    211         {
    212           if ( ++index >= 17 )
    213             return 1;
    214         }
    215       }
    216     }
    217   }
    218   return 0;
    219 }

    到这里思路已经很明确了,16位输入,分成两部分进行异或操作,验证x^2-7*y^2=8

    限定条件为

    0x100000000000000<x < 0x1000000000000000,(x为8字节,且第8字节<0x10)

    0x100000000000000<y<x (y为8字节,)

    在进行一步异或即可得到原输入

    x^2-7*y^2=8为非标准佩尔方程,求解使用了wolframalpha

    https://www.wolframalpha.com/input/?i=x%5E2-7y%5E2%3D8,72057594037927936%3Cx+%3C+1152921504606846976,72057594037927936%3Cy%3Cx

     1 x=385044246406735194
     2 y=145533045678356702
     3 
     4 s_xor1=0x646e9881e38c9616
     5 s_xor2=0x4f484dbe81dc0884
     6 
     7 t1=hex(x^s_xor1)[2:]
     8 t2=hex(y^s_xor2)[2:]
     9 
    10 m1=[]
    11 m2=[]
    12 for i in range(0,16,2):
    13     m1.append(int(t1[i:i+2],16))
    14     m2.append(int(t2[i:i+2],16))
    15 a=''.join(map(chr,m1))
    16 b=''.join(map(chr,m2))
    17 print(a[-1::-1]+b[-1::-1])
    18 # L3mZ2k9aZ0a36DMM

    链接:https://pan.baidu.com/s/1ZpzCus2BdlSujkVRBQZZxQ
    提取码:qrlz
    复制这段内容后打开百度网盘手机App,操作更方便哦

  • 相关阅读:
    【664】日常记录
    【663】dataframe 删掉指定行或者列
    【662】TensorFlow GPU 相关配置
    【661】Python split 指定多个分隔符
    【660】TensorFlow 或者 keras 版本问题
    FFMPEG视音频编解码
    cpplint中filter参数
    升级pip之后出现sys.stderr.write(f“ERROR: {exc}“)
    特征点三角化恢复3D点
    VIO——陀螺仪零偏估计
  • 原文地址:https://www.cnblogs.com/DirWang/p/11228038.html
Copyright © 2020-2023  润新知