WriteUp-i春秋-溯源

一个简单的逆向qwq

 

 叫你输入key,给出提示信息

--

 

 无壳

C++编写

老规矩:拖IDA

搜索fail找到了main函数

 

 

 

 这个main流程有点复杂qwq

我们看看它的伪代码:

 

全代码:

  1 _DWORD *__fastcall sub_401D90(_DWORD *a1, _DWORD *a2)
  2 {
  3   _DWORD *v2; // esi
  4   _DWORD *v3; // ebx
  5   int v4; // eax
  6   signed int v5; // edi
  7   int v6; // ecx
  8   int v7; // eax
  9   void (__thiscall ***v8)(_DWORD, signed int); // eax
 10   bool v9; // cf
 11   _BYTE *v10; // eax
 12   int v11; // ecx
 13   int v12; // eax
 14   unsigned int v13; // edi
 15   int i; // eax
 16   char v15; // dl
 17   unsigned int v16; // edi
 18   _DWORD *v17; // eax
 19   _DWORD *v18; // eax
 20   int v19; // eax
 21   bool v20; // zf
 22   int v21; // eax
 23   int v22; // ecx
 24   int v24; // [esp+0h] [ebp-4Ch]
 25   int v25; // [esp+4h] [ebp-48h]
 26   int v26; // [esp+8h] [ebp-44h]
 27   int v27; // [esp+Ch] [ebp-40h]
 28   char v28; // [esp+10h] [ebp-3Ch]
 29   int v29; // [esp+14h] [ebp-38h]
 30   _DWORD *v30; // [esp+18h] [ebp-34h]
 31   char v31; // [esp+1Ch] [ebp-30h]
 32   int v32; // [esp+20h] [ebp-2Ch]
 33   int v33; // [esp+24h] [ebp-28h]
 34   _DWORD *v34; // [esp+28h] [ebp-24h]
 35   int v35; // [esp+2Ch] [ebp-20h]
 36   int v36; // [esp+30h] [ebp-1Ch]
 37   int v37; // [esp+34h] [ebp-18h]
 38   int v38; // [esp+38h] [ebp-14h]
 39   int *v39; // [esp+3Ch] [ebp-10h]
 40   int v40; // [esp+40h] [ebp-Ch]
 41   int v41; // [esp+44h] [ebp-8h]
 42   int v42; // [esp+48h] [ebp-4h]
 43 
 44   v39 = &v24;
 45   v2 = a2;
 46   v3 = a1;
 47   v34 = a1;
 48   v4 = *a1;
 49   v5 = 0;
 50   v32 = 0;
 51   HIBYTE(v38) = 0;
 52   v30 = a1;
 53   v6 = *(_DWORD *)((char *)a1 + *(_DWORD *)(v4 + 4) + 56);
 54   if ( v6 )
 55     (*(void (**)(void))(*(_DWORD *)v6 + 4))();
 56   v42 = 0;
 57   v31 = std::basic_istream<char,std::char_traits<char>>::_Ipfx(v3, 0);
 58   v42 = 1;
 59   if ( v31 )
 60   {
 61     v7 = std::ios_base::getloc((char *)v3 + *(_DWORD *)(*v3 + 4), &v28);
 62     LOBYTE(v42) = 2;
 63     v33 = sub_401940(v7);
 64     LOBYTE(v42) = 3;
 65     if ( v29 )
 66     {
 67       v8 = (void (__thiscall ***)(_DWORD, signed int))(*(int (**)(void))(*(_DWORD *)v29 + 8))();
 68       if ( v8 )
 69         (**v8)(v8, 1);
 70     }
 71     v9 = v2[5] < 0x10u;
 72     v2[4] = 0;
 73     if ( v9 )
 74       v10 = v2;
 75     else
 76       v10 = (_BYTE *)*v2;
 77     *v10 = 0;
 78     LOBYTE(v42) = 4;
 79     v11 = *(_DWORD *)(*v3 + 4);
 80     v12 = *(_DWORD *)((char *)v3 + v11 + 36);
 81     v13 = *(_DWORD *)((char *)v3 + v11 + 32);
 82     v37 = *(_DWORD *)((char *)v3 + v11 + 32);
 83     if ( v12 >= 0 && (v12 > 0 || v13) && (v36 = v12, v13 < 0xFFFFFFFE) )
 84     {
 85       v36 = v12;
 86     }
 87     else
 88     {
 89       v13 = -2;
 90       v37 = -2;
 91     }
 92     for ( i = std::basic_streambuf<char,std::char_traits<char>>::sgetc(*(_DWORD *)((char *)v3 + v11 + 56));
 93           ;
 94           i = std::basic_streambuf<char,std::char_traits<char>>::snextc(*(_DWORD *)((char *)v3
 95                                                                                   + *(_DWORD *)(v19 + 4)
 96                                                                                   + 56)) )
 97     {
 98       v15 = i;
 99       v36 = i;
100       if ( !v13 )
101         break;
102       if ( i == -1 )
103       {
104         v5 = 1;
105         goto LABEL_38;
106       }
107       if ( *(_BYTE *)(*(_DWORD *)(v33 + 12) + 2 * (unsigned __int8)i) & 0x48 )
108         break;
109       if ( (unsigned int)~v2[4] <= 1 )
110         sub_401780();
111       v16 = v2[4] + 1;
112       if ( v2[4] == -1 )
113       {
114         v9 = v2[5] < 0x10u;
115         v2[4] = 0;
116         if ( v9 )
117           *(_BYTE *)v2 = 0;
118         else
119           *(_BYTE *)*v2 = 0;
120       }
121       else
122       {
123         if ( v2[5] < v16 )
124         {
125           sub_401790(v2, v16);
126           v15 = v36;
127         }
128         if ( v2[5] < 0x10u )
129           v17 = v2;
130         else
131           v17 = (_DWORD *)*v2;
132         *((_BYTE *)v17 + v2[4]) = v15;
133         v9 = v2[5] < 0x10u;
134         v2[4] = v16;
135         if ( v9 )
136           v18 = v2;
137         else
138           v18 = (_DWORD *)*v2;
139         *((_BYTE *)v18 + v16) = 0;
140       }
141       v19 = *v3;
142       v13 = v37 - 1;
143       HIBYTE(v38) = 1;
144       --v37;
145     }
146     v5 = 0;
147 LABEL_38:
148     v42 = 1;
149   }
150   v20 = HIBYTE(v38) == 0;
151   v21 = *(_DWORD *)(*v3 + 4);
152   *(_DWORD *)((char *)v3 + v21 + 32) = 0;
153   *(_DWORD *)((char *)v3 + v21 + 36) = 0;
154   if ( v20 )
155     v5 |= 2u;
156   std::basic_ios<char,std::char_traits<char>>::setstate(
157     (char *)v3 + *(_DWORD *)(*v3 + 4),
158     v5,
159     0,
160     v24,
161     v25,
162     v26,
163     v27,
164     *(_DWORD *)&v28,
165     v29,
166     v30,
167     *(_DWORD *)&v31,
168     v32,
169     v33,
170     v34,
171     v35,
172     v36,
173     v37,
174     v38,
175     v39,
176     v40,
177     v41,
178     v42);
179   v42 = 6;
180   v22 = *(_DWORD *)((char *)v30 + *(_DWORD *)(*v30 + 4) + 56);
181   if ( v22 )
182     (*(void (**)(void))(*(_DWORD *)v22 + 8))();
183   return v3;
184 }
View IDA Code

 

简单分析一下可以看出:

sub_401D90这个函数是获取输入的(疑似有处理)

sub_401300是处理输入的

sub_401120也有点关系

后面有简单的处理与验证(暂时不管qwq)

 

先看看sub_401D90:

_DWORD *__fastcall sub_401D90(_DWORD *a1, _DWORD *a2)
{
  _DWORD *v2; // esi
  _DWORD *v3; // ebx
  int v4; // eax
  signed int v5; // edi
  int v6; // ecx
  int v7; // eax
  void (__thiscall ***v8)(_DWORD, signed int); // eax
  bool v9; // cf
  _BYTE *v10; // eax
  int v11; // ecx
  int v12; // eax
  unsigned int v13; // edi
  int i; // eax
  char v15; // dl
  unsigned int v16; // edi
  _DWORD *v17; // eax
  _DWORD *v18; // eax
  int v19; // eax
  bool v20; // zf
  int v21; // eax
  int v22; // ecx
  int v24; // [esp+0h] [ebp-4Ch]
  int v25; // [esp+4h] [ebp-48h]
  int v26; // [esp+8h] [ebp-44h]
  int v27; // [esp+Ch] [ebp-40h]
  char v28; // [esp+10h] [ebp-3Ch]
  int v29; // [esp+14h] [ebp-38h]
  _DWORD *v30; // [esp+18h] [ebp-34h]
  char v31; // [esp+1Ch] [ebp-30h]
  int v32; // [esp+20h] [ebp-2Ch]
  int v33; // [esp+24h] [ebp-28h]
  _DWORD *v34; // [esp+28h] [ebp-24h]
  int v35; // [esp+2Ch] [ebp-20h]
  int v36; // [esp+30h] [ebp-1Ch]
  int v37; // [esp+34h] [ebp-18h]
  int v38; // [esp+38h] [ebp-14h]
  int *v39; // [esp+3Ch] [ebp-10h]
  int v40; // [esp+40h] [ebp-Ch]
  int v41; // [esp+44h] [ebp-8h]
  int v42; // [esp+48h] [ebp-4h]

  v39 = &v24;
  v2 = a2;
  v3 = a1;
  v34 = a1;
  v4 = *a1;
  v5 = 0;
  v32 = 0;
  HIBYTE(v38) = 0;
  v30 = a1;
  v6 = *(_DWORD *)((char *)a1 + *(_DWORD *)(v4 + 4) + 56);
  if ( v6 )
    (*(void (**)(void))(*(_DWORD *)v6 + 4))();
  v42 = 0;
  v31 = std::basic_istream<char,std::char_traits<char>>::_Ipfx(v3, 0);
  v42 = 1;
  if ( v31 )
  {
    v7 = std::ios_base::getloc((char *)v3 + *(_DWORD *)(*v3 + 4), &v28);
    LOBYTE(v42) = 2;
    v33 = sub_401940(v7);
    LOBYTE(v42) = 3;
    if ( v29 )
    {
      v8 = (void (__thiscall ***)(_DWORD, signed int))(*(int (**)(void))(*(_DWORD *)v29 + 8))();
      if ( v8 )
        (**v8)(v8, 1);
    }
    v9 = v2[5] < 0x10u;
    v2[4] = 0;
    if ( v9 )
      v10 = v2;
    else
      v10 = (_BYTE *)*v2;
    *v10 = 0;
    LOBYTE(v42) = 4;
    v11 = *(_DWORD *)(*v3 + 4);
    v12 = *(_DWORD *)((char *)v3 + v11 + 36);
    v13 = *(_DWORD *)((char *)v3 + v11 + 32);
    v37 = *(_DWORD *)((char *)v3 + v11 + 32);
    if ( v12 >= 0 && (v12 > 0 || v13) && (v36 = v12, v13 < 0xFFFFFFFE) )
    {
      v36 = v12;
    }
    else
    {
      v13 = -2;
      v37 = -2;
    }
    for ( i = std::basic_streambuf<char,std::char_traits<char>>::sgetc(*(_DWORD *)((char *)v3 + v11 + 56));
          ;
          i = std::basic_streambuf<char,std::char_traits<char>>::snextc(*(_DWORD *)((char *)v3
                                                                                  + *(_DWORD *)(v19 + 4)
                                                                                  + 56)) )
    {
      v15 = i;
      v36 = i;
      if ( !v13 )
        break;
      if ( i == -1 )
      {
        v5 = 1;
        goto LABEL_38;
      }
      if ( *(_BYTE *)(*(_DWORD *)(v33 + 12) + 2 * (unsigned __int8)i) & 0x48 )
        break;
      if ( (unsigned int)~v2[4] <= 1 )
        sub_401780();
      v16 = v2[4] + 1;
      if ( v2[4] == -1 )
      {
        v9 = v2[5] < 0x10u;
        v2[4] = 0;
        if ( v9 )
          *(_BYTE *)v2 = 0;
        else
          *(_BYTE *)*v2 = 0;
      }
      else
      {
        if ( v2[5] < v16 )
        {
          sub_401790(v2, v16);
          v15 = v36;
        }
        if ( v2[5] < 0x10u )
          v17 = v2;
        else
          v17 = (_DWORD *)*v2;
        *((_BYTE *)v17 + v2[4]) = v15;
        v9 = v2[5] < 0x10u;
        v2[4] = v16;
        if ( v9 )
          v18 = v2;
        else
          v18 = (_DWORD *)*v2;
        *((_BYTE *)v18 + v16) = 0;
      }
      v19 = *v3;
      v13 = v37 - 1;
      HIBYTE(v38) = 1;
      --v37;
    }
    v5 = 0;
LABEL_38:
    v42 = 1;
  }
  v20 = HIBYTE(v38) == 0;
  v21 = *(_DWORD *)(*v3 + 4);
  *(_DWORD *)((char *)v3 + v21 + 32) = 0;
  *(_DWORD *)((char *)v3 + v21 + 36) = 0;
  if ( v20 )
    v5 |= 2u;
  std::basic_ios<char,std::char_traits<char>>::setstate(
    (char *)v3 + *(_DWORD *)(*v3 + 4),
    v5,
    0,
    v24,
    v25,
    v26,
    v27,
    *(_DWORD *)&v28,
    v29,
    v30,
    *(_DWORD *)&v31,
    v32,
    v33,
    v34,
    v35,
    v36,
    v37,
    v38,
    v39,
    v40,
    v41,
    v42);
  v42 = 6;
  v22 = *(_DWORD *)((char *)v30 + *(_DWORD *)(*v30 + 4) + 56);
  if ( v22 )
    (*(void (**)(void))(*(_DWORD *)v22 + 8))();
  return v3;
}
View sub_401D90 Code

 

 

 有……有点复杂qwq

结合OD分析一波

这个v32(对应esp+0x30)

 

 

 我们根据之前的分析可以推测这个v32是存储输入的指针

在od里看到

 

 

 访问这个指针:

 

 

 与输入完全一致

我们可以简单地把sub_401D90看成获取输入字符(自己懒得分析sub_401D90了qwq)

然后是sub_401300

我们可以先看看v35

 

 

 可以看到是一堆0x20与0x00

运行sub_401D90前v35依然是这样

所以我们可以认为sub_401D90对v35无影响

我们接着开始分析sub_401300

unsigned int __fastcall sub_401300(_DWORD *a1, int a2)
{
  signed int v2; // esi
  _DWORD *v3; // edi
  __m128i v4; // xmm5
  __m128i v5; // xmm7
  unsigned int result; // eax
  __m128i v7; // xmm2
  __m128i v8; // xmm1
  __m128i v9; // xmm2
  __m128i v10; // xmm1
  int v11; // edx
  unsigned int v12; // eax
  int v13; // ebx
  int v14; // edi
  int v15; // ebx
  unsigned int *v16; // esi
  int v17; // [esp+10h] [ebp-8h]
  int v18; // [esp+14h] [ebp-4h]

  v2 = 0;
  v17 = a2;
  v3 = a1;
  if ( dword_40541C < 2 )
    goto LABEL_19;
  v4 = _mm_cvtsi32_si128(5u);
  v5 = _mm_cvtsi32_si128(0x1Fu);
  do
  {
    result = v2 + 4;
    v7 = _mm_add_epi32(_mm_shuffle_epi32(_mm_cvtsi32_si128(v2), 0), (__m128i)xmmword_403630);
    v8 = _mm_sra_epi32(
           (__m128i)_mm_shuffle_ps(
                      (__m128)_mm_mul_epi32(_mm_unpacklo_epi32(v7, v7), (__m128i)xmmword_403650),
                      (__m128)_mm_mul_epi32(_mm_unpackhi_epi32(v7, v7), (__m128i)xmmword_403650),
                      221),
           v4);
    *(__m128i *)(a2 + 4 * v2) = _mm_sub_epi32(
                                  v7,
                                  _mm_mullo_epi32(_mm_add_epi32(_mm_srl_epi32(v8, v5), v8), (__m128i)xmmword_403640));
    v9 = _mm_add_epi32(_mm_shuffle_epi32(_mm_cvtsi32_si128(v2 + 4), 0), (__m128i)xmmword_403630);
    v10 = _mm_sra_epi32(
            (__m128i)_mm_shuffle_ps(
                       (__m128)_mm_mul_epi32(_mm_unpacklo_epi32(v9, v9), (__m128i)xmmword_403650),
                       (__m128)_mm_mul_epi32(_mm_unpackhi_epi32(v9, v9), (__m128i)xmmword_403650),
                       221),
            v4);
    *(__m128i *)(a2 + 4 * v2 + 16) = _mm_sub_epi32(
                                       v9,
                                       _mm_mullo_epi32(
                                         _mm_add_epi32(_mm_srl_epi32(v10, v5), v10),
                                         (__m128i)xmmword_403640));
    v2 += 8;
  }
  while ( v2 < 992 );
  if ( v2 < 999 )
  {
LABEL_19:
    do
    {
      result = 100 * (v2 / 100);
      *(_DWORD *)(a2 + 4 * v2) = v2 % 100;
      ++v2;
    }
    while ( v2 < 999 );
  }
  v11 = 0;
  v18 = 0;
  if ( a1[4] == 200 )
  {
    v12 = a1[5];
    if ( v12 >= 0x10 )
      a1 = (_DWORD *)*a1;
    if ( v12 >= 0x10 )
      v3 = (_DWORD *)*v3;
    result = (unsigned int)(v3 + 50);
    v13 = (int)(v3 + 50);
    v14 = 0;
    v15 = v13 - (_DWORD)a1;
    if ( (unsigned int)a1 > result )
      v15 = 0;
    if ( v15 )
    {
      do
      {
        v16 = (unsigned int *)(v17 + 4 * (v11 / 2));
        result = 16 * *v16 - 65 + *(char *)a1;
        v11 = v18 + 1;
        *v16 = result;
        v18 = v11;
        if ( !(v11 & 1) )
        {
          result = v11 / 2;
          *(_DWORD *)(v17 + 4 * (v11 / 2)) = 0;
        }
        ++v14;
        a1 = (_DWORD *)((char *)a1 + 1);
      }
      while ( v14 != v15 );
    }
  }
  return result;
}
View IDA Code

 

我们简单魔改一下这个代码:

 

  1 unsigned int __fastcall sub_401300(_DWORD *input, int a2)
  2 {
  3   signed int counter_1; // esi
  4   _DWORD *in_; // edi
  5   __m128i read_1; // xmm5
  6   __m128i read_2; // xmm7
  7   unsigned int result; // eax
  8   __m128i read_temp_2; // xmm2
  9   __m128i read_temp_1; // xmm1
 10   __m128i read_temp_4; // xmm2
 11   __m128i read_temp_3; // xmm1
 12   int t1; // edx
 13   unsigned int v12; // eax
 14   int v13; // ebx
 15   int i; // edi
 16   int v15; // ebx
 17   unsigned int *v16; // esi
 18   int a2_copy; // [esp+10h] [ebp-8h]
 19   int temp_18; // [esp+14h] [ebp-4h]
 20 
 21   counter_1 = 0;
 22   a2_copy = a2;
 23   in_ = input;
 24   if ( dword_40541C < 2 )
 25     goto LABEL_19;
 26   read_1 = _mm_cvtsi32_si128(5u);
 27   read_2 = _mm_cvtsi32_si128(0x1Fu);
 28   do
 29   {
 30     result = counter_1 + 4;
 31     read_temp_2 = _mm_add_epi32(_mm_shuffle_epi32(_mm_cvtsi32_si128(counter_1), 0), (__m128i)constant_xmm_2);
 32     read_temp_1 = _mm_sra_epi32(
 33                     (__m128i)_mm_shuffle_ps(
 34                                (__m128)_mm_mul_epi32(
 35                                          _mm_unpacklo_epi32(read_temp_2, read_temp_2),
 36                                          (__m128i)constant_xmm_3),
 37                                (__m128)_mm_mul_epi32(
 38                                          _mm_unpackhi_epi32(read_temp_2, read_temp_2),
 39                                          (__m128i)constant_xmm_3),
 40                                221),
 41                     read_1);
 42     *(__m128i *)(a2 + 4 * counter_1) = _mm_sub_epi32(
 43                                          read_temp_2,
 44                                          _mm_mullo_epi32(
 45                                            _mm_add_epi32(_mm_srl_epi32(read_temp_1, read_2), read_temp_1),
 46                                            (__m128i)constant_xmm_1));
 47     read_temp_4 = _mm_add_epi32(_mm_shuffle_epi32(_mm_cvtsi32_si128(counter_1 + 4), 0), (__m128i)constant_xmm_2);
 48     read_temp_3 = _mm_sra_epi32(
 49                     (__m128i)_mm_shuffle_ps(
 50                                (__m128)_mm_mul_epi32(
 51                                          _mm_unpacklo_epi32(read_temp_4, read_temp_4),
 52                                          (__m128i)constant_xmm_3),
 53                                (__m128)_mm_mul_epi32(
 54                                          _mm_unpackhi_epi32(read_temp_4, read_temp_4),
 55                                          (__m128i)constant_xmm_3),
 56                                221),
 57                     read_1);
 58     *(__m128i *)(a2 + 4 * counter_1 + 16) = _mm_sub_epi32(
 59                                               read_temp_4,
 60                                               _mm_mullo_epi32(
 61                                                 _mm_add_epi32(_mm_srl_epi32(read_temp_3, read_2), read_temp_3),
 62                                                 (__m128i)constant_xmm_1));
 63     counter_1 += 8;
 64   }
 65   while ( counter_1 < 992 );   // 数据读入内存(没啥用)
 66 
 67 
 68   if ( counter_1 < 999 )
 69   {
 70 LABEL_19:
 71     do
 72     {
 73       result = 100 * (counter_1 / 100);
 74       *(_DWORD *)(a2 + 4 * counter_1) = counter_1 % 100;
 75       ++counter_1;
 76     }
 77     while ( counter_1 < 999 );
 78   }
 79 
 80 
 81   t1 = 0;
 82   temp_18 = 0;
 83   if ( len(input)==200)
 84   {
 85     v12 = input[5];
 86     if ( v12 >= 0x10 )
 87       input = (_DWORD *)*input;
 88       in_ = (_DWORD *)*in_;
 89     //字符串过长时  传入的字符串地址会放在input指针里
 90 
 91 
 92     result = (unsigned int)(in_ + 200);
 93     v13 = result;
 94     i = 0;
 95     v15 = 200;
 96 
 97     if ( (unsigned int)input > result )
 98       v15 = 0;
 99 
100 
101     if ( v15 )
102     {
103 
104 
105       for(int i;i<200;++i)
106       {
107 
108         a2_copy[i/2] = 16 * a2_copy[i/2] - 65 + input[i];
109         if ( (i+1) % 2 == 0 )
110         {
111           a2_copy[(i+1)/2] = 0;
112         }
113       }
114       /*
115       改变输入copy的值 字符串 每两个字符为一个单位 把一个单位转化成一个数
116       AACABB 变成 数 0000 0020  0011   
117        */
118 
119     }
120   }
121 
122 
123   return result;
124 }
View chaneged Code

这个代码把200位的输入字符修改为100位的数字(dword)

每两个字符转成一个数字

第0,1 个字符 的 ASCII码值 - 65("A") 分别作为dword数字的第1个16进制位,第0个16进制位 其他填0

例:

input: CB

output: 0x00000021

 

接下来看处理后的输入经历了什么(sub_401120):

 1 _DWORD *__thiscall sub_401120(_DWORD *this, int a2, int a3)
 2 {
 3   _DWORD *self; // esi
 4   int v4; // eax
 5   int counter; // ebx
 6   _DWORD *v6; // edi
 7   int -v4-8; // ecx
 8   signed int v9; // [esp+28h] [ebp-4h]
 9   int v10; // [esp+34h] [ebp+8h]
10 
11   self = this;
12   *this = 10;
13   this[1] = operator new[](0x190u);//分配内存
14   v4 = a2;
15   v9 = 8;
16 
17   v10 = 4 - a2;
18   counter = 0;
19   v6 = (_DWORD *)(v4 + 8);
20   -v4-8 = -8 - v4;
21   do
22   {
23     *(_DWORD *)((char *)v6 + -v4-8 + self[1]) = *(v6 - 2);
24     if ( !*(v6 - 2) )
25     {
26       self[2] = counter;
27       self[3] = 0;
28     }
29 
30     *(_DWORD *)((char *)v6 + -v4-8 + self[1] + 4) = *(v6 - 1);
31     //复制数据   到self (v6 - v4 = 8)
32 
33 
34     if ( !*(v6 - 1) )
35     {
36       self[2] = counter;
37       self[3] = 1;
38     }
39     *(_DWORD *)(v9 + self[1]) = *v6;
40     if ( !*v6 )
41     {
42       self[2] = counter;
43       self[3] = 2;
44     }
45     *(_DWORD *)((char *)v6 + 4-v4 + self[1]) = v6[1];
46     if ( !v6[1] )
47     {
48       self[2] = counter;
49       self[3] = 3;
50     }
51     *(_DWORD *)((char *)v6 + 8 - v4 + self[1]) = v6[2];
52     if ( !v6[2] )
53     {
54       self[2] = counter;
55       self[3] = 4;
56     }
57     *(_DWORD *)((char *)v6 + 12 - v4 + self[1]) = v6[3];
58     if ( !v6[3] )
59     {
60       self[2] = counter;
61       self[3] = 5;
62     }
63     *(_DWORD *)((char *)v6 + 16 - v4 + self[1]) = v6[4];
64     if ( !v6[4] )
65     {
66       self[2] = counter;
67       self[3] = 6;
68     }
69     *(_DWORD *)((char *)v6 + 20 - v4 + self[1]) = v6[5];
70     if ( !v6[5] )
71     {
72       self[2] = counter;
73       self[3] = 7;
74     }
75     *(_DWORD *)((char *)v6 + 24 - v4 + self[1]) = v6[6];
76     if ( !v6[6] )
77     {
78       self[2] = counter;
79       self[3] = 8;
80     }
81     *(_DWORD *)((char *)v6 + 28 - v4 + self[1]) = v6[7];
82     if ( !v6[7] )
83     {
84       self[2] = counter;
85       self[3] = 9;
86     }
87     ++counter;
88     -v4-8 = -8 - v4;
89     v6 += 10;
90     v9 += 40;
91   }
92   while ( v9 < 408 );
93   return self;
94 }
95 //复制数据
View changed Code

看起来很吓人其实就是个简单的数据复制

 

我们来看看这个this(也就是self)在哪:

 

 this所在的地址是某常量(local.1024)

(对应IDA中的代码)

 

 

我们再看到主函数main的代码:

  1 int __cdecl main(int argc, const char **argv, const char **envp)
  2 {
  3   int v3; // eax
  4   int v4; // ST04_4
  5   int v5; // ecx
  6   int v6; // eax
  7   int v7; // eax
  8   signed int v8; // edi
  9   unsigned int v9; // ecx
 10   int v10; // edx
 11   int v11; // esi
 12   int v12; // eax
 13   _DWORD *v13; // edi
 14   int v14; // ecx
 15   int v15; // esi
 16   int i; // eax
 17   const char *j; // edx
 18   int v18; // eax
 19   int v19; // ST04_4
 20   char *v20; // ecx
 21   unsigned int v21; // eax
 22   unsigned int v22; // ecx
 23   int v24; // [esp+10h] [ebp-1008h]
 24   int v25; // [esp+14h] [ebp-1004h]
 25   int v26; // [esp+18h] [ebp-1000h]
 26   _DWORD *Memory; // [esp+1Ch] [ebp-FFCh]
 27   int v28; // [esp+20h] [ebp-FF8h]
 28   int v29; // [esp+24h] [ebp-FF4h]
 29   signed int v30; // [esp+28h] [ebp-FF0h]
 30   signed int v31; // [esp+2Ch] [ebp-FECh]
 31   void *v32; // [esp+30h] [ebp-FE8h]
 32   int v33; // [esp+40h] [ebp-FD8h]
 33   unsigned int v34; // [esp+44h] [ebp-FD4h]
 34   char v35; // [esp+48h] [ebp-FD0h]
 35   __int128 v36; // [esp+FE8h] [ebp-30h]
 36   __int128 v37; // [esp+FF8h] [ebp-20h]
 37   int v38; // [esp+1014h] [ebp-4h]
 38 
 39   v3 = sub_401A30(std::cout, "please input key:", sub_401C60);
 40   std::basic_ostream<char,std::char_traits<char>>::operator<<(v3, v4);
 41   v33 = 0;
 42   v34 = 15;
 43   LOBYTE(v32) = 0;
 44   v38 = 0;
 45   sub_401D90(std::cin, &v32);
 46   sub_401300(&v32, &v35);
 47   sub_401120(&v35, v5);
 48   v6 = 999;
 49   LOBYTE(v38) = 1;
 50   v30 = 999;
 51   do
 52   {
 53     v7 = (unsigned __int8)byte_403230[v6];
 54     v8 = 4;
 55     v31 = 4;
 56     do
 57     {
 58       v9 = v7 & 3;
 59       v24 = v7 >> 2;
 60       v10 = 5 - v9;
 61       v36 = xmmword_403660;
 62       if ( v9 < 2 )
 63         v10 = 1 - v9;
 64       v37 = xmmword_403620;
 65       v11 = v28 + *((_DWORD *)&v36 + 2 * v10);
 66       v12 = v29 + *((_DWORD *)&v36 + 2 * v10 + 1);
 67       v25 = v11;
 68       if ( v11 >= 0 && v11 < v26 && v12 >= 0 && v12 < v26 )
 69       {
 70         v13 = &Memory[v29 + v28 * v26];
 71         v14 = v12 + v11 * v26;
 72         v15 = Memory[v14];
 73         Memory[v14] = *v13;
 74         *v13 = v15;
 75         v8 = v31;
 76         v28 = v25;
 77         v29 = v12;
 78       }
 79       v7 = v24;
 80       v31 = --v8;
 81     }
 82     while ( v8 );
 83     v6 = v30-- - 1;
 84   }
 85   while ( v30 >= 0 );
 86   for ( i = 0; i < v26 * v26; ++i )
 87   {
 88     if ( Memory[i] != i )
 89       goto LABEL_20;
 90   }
 91   for ( j = "success"; ; j = "fail" )
 92   {
 93     v18 = sub_401A30(std::cout, j, sub_401C60);
 94     std::basic_ostream<char,std::char_traits<char>>::operator<<(v18, v19);
 95     j_j_free(Memory);
 96     if ( v34 < 0x10 )
 97       break;
 98     v20 = (char *)v32;
 99     if ( v34 + 1 < 0x1000 )
100       goto LABEL_28;
101     if ( !((unsigned __int8)v32 & 0x1F) )
102     {
103       v21 = *((_DWORD *)v32 - 1);
104       if ( v21 >= (unsigned int)v32 )
105         v21 = invalid_parameter_noinfo_noreturn(v32);
106       v22 = (unsigned int)&v20[-v21];
107       if ( v22 < 4 )
108         v21 = invalid_parameter_noinfo_noreturn(v22);
109       if ( v22 > 0x23 )
110         v21 = invalid_parameter_noinfo_noreturn(v22);
111       v20 = (char *)v21;
112 LABEL_28:
113       j_free(v20);
114       return 0;
115     }
116     invalid_parameter_noinfo_noreturn(v32);
117 LABEL_20:
118     ;
119   }
120   return 0;
121 }
View IDA Code

我魔改了一下让它更易读:

  1 int __cdecl main(int argc, const char **argv, const char **envp)
  2 {
  3   int v3; // eax
  4   int v4; // ST04_4
  5   int temp; // ecx
  6   int i; // eax
  7   int b; // eax
  8   signed int j; // edi
  9   unsigned int low; // ecx
 10   int w; // edx
 11   int array1; // esi
 12   int array0; // eax
 13   _DWORD *po; // edi
 14   int v14; // ecx
 15   int temp; // esi
 16   int i; // eax
 17   const char *j; // edx
 18   int v18; // eax
 19   int v19; // ST04_4
 20   char *v20; // ecx
 21   unsigned int v21; // eax
 22   unsigned int v22; // ecx
 23   int high; // [esp+10h] [ebp-1008h]
 24   int _useless; // [esp+14h] [ebp-1004h]
 25   int 0x0A; // [esp+18h] [ebp-1000h]
 26   _DWORD *Memory; // [esp+1Ch] [ebp-FFCh]
 27   int d1; // [esp+20h] [ebp-FF8h]
 28   int d0; // [esp+24h] [ebp-FF4h]
 29   signed int q; // [esp+28h] [ebp-FF0h]
 30   signed int k; // [esp+2Ch] [ebp-FECh]
 31   void *v32; // [esp+30h] [ebp-FE8h]
 32   int v33; // [esp+40h] [ebp-FD8h]
 33   unsigned int v34; // [esp+44h] [ebp-FD4h]
 34   char input; // [esp+48h] [ebp-FD0h]
 35   __int128 xmm; // [esp+FE8h] [ebp-30h]
 36   __int128 useless; // [esp+FF8h] [ebp-20h]
 37   int v38; // [esp+1014h] [ebp-4h]
 38 
 39   v3 = sub_401A30(std::cout, "please input key:", sub_401C60);
 40   std::basic_ostream<char,std::char_traits<char>>::operator<<(v3, v4);
 41   v33 = 0;
 42   v34 = 15;
 43   LOBYTE(v32) = 0;
 44   v38 = 0;
 45   sub_401D90(std::cin, &v32);//输入数据到v32
 46   sub_401300(&v32, &input);
 47   sub_401120(&input, temp);//复制数据到self
 48 
 49 
 50   i = 999;
 51   LOBYTE(v38) = 1;
 52   q = 999;
 53   do
 54   {
 55     b = (unsigned __int8)table[q];
 56     j = 4;
 57     for(int j=4; j>0 ;j--)
 58     {
 59       low = b & 3;//低2位
 60       high = b >> 2;//高6位 (算上符号位)
 61       w = 5 - low;
 62       if ( low < 2 )
 63         w = 1 - low;
 64       xmm = xmmword_403660;
 65       useless = xmmword_403620;
 66       array1 = d1 + xmm[2 * w];
 67       array0 = d0 + xmm[2 * w + 1];
 68       if (!(array1 >= 0 && array1 < 0x0A && array0 >= 0 && array0 < 0x0A))
 69       {
 70         printf("fail\n");
 71         return 0;
 72       }//数组越界 失败
 73       temp = Memory[array1][array0];
 74       Memory[array1][array0] = Memory[d1][d0];
 75       Memory[d1][d0] = temp;
 76 
 77 
 78 
 79       d1 = array1;
 80       d0 = array0;
 81       b = high;
 82       j--
 83     }
 84 
 85 
 86     q--;
 87   }
 88   while ( q >= 0 );//循环
 89 
 90   for ( i = 0; i < 0x0A * 0x0A; ++i )
 91   {
 92     if ( Memory[i] != i )
 93       goto LABEL_20;//判断
 94   }
 95 
 96 
 97 
 98   for ( j = "success"; ; j = "fail" )
 99   {
100     v18 = sub_401A30(std::cout, j, sub_401C60);
101     std::basic_ostream<char,std::char_traits<char>>::operator<<(v18, v19);
102     j_j_free(Memory);
103     if ( v34 < 0x10 )
104       break;
105     v20 = (char *)v32;
106     if ( v34 + 1 < 0x1000 )
107       goto LABEL_28;
108     if ( !((unsigned __int8)v32 & 0x1F) )
109     {
110       v21 = *((_DWORD *)v32 - 1);
111       if ( v21 >= (unsigned int)v32 )
112         v21 = invalid_parameter_noinfo_noreturn(v32);
113       v22 = (unsigned int)&v20[-v21];
114       if ( v22 < 4 )
115         v21 = invalid_parameter_noinfo_noreturn(v22);
116       if ( v22 > 0x23 )
117         v21 = invalid_parameter_noinfo_noreturn(v22);
118       v20 = (char *)v21;
119 LABEL_28:
120       j_free(v20);
121       return 0;
122     }
123     invalid_parameter_noinfo_noreturn(v32);
124 LABEL_20://失败qwq
125     ;
126   }
127   return 0;
128 }
View Changed Code

 

注意,我们需要知道

这个 d1,d0(Changed Code 中)

运行完后是什么值

d1,d0

分别对应着IDA伪代码中的v28,v29

 

 OD中运行完后看到结果:

 

 

找到xmm

 

 数组是

[0, 1, 0, -1, 1, 0, -1, 0]

现在就可以复现出整个程序的逻辑并写出逆向脚本了:

import numpy as np

table = (160, 142, 226, 128, 189, 158, 130, 145, 29, 181, 223, 138, 200, 152, 4, 76, 25, 83, 197, 181, 50, 204, 116, 198
         , 72, 96, 183, 251, 41, 63, 46, 254, 237, 155, 86, 206, 116, 155, 94, 132, 228, 54, 226, 88, 104, 140, 83, 246,
         81, 19, 145, 255, 1, 140, 65, 82, 71, 102, 206, 34, 69, 75, 228, 220, 104, 128, 91, 76, 206, 194, 115, 158,
         123, 2, 4, 114, 85, 189, 0, 149, 132, 45, 219, 153, 154, 31, 179, 30, 108, 199, 224, 34, 223, 110, 235, 106,
         181, 124, 175, 250, 214, 172, 45, 74, 147, 120, 191, 60, 26, 210, 224, 47, 221, 70, 99, 142, 20, 78, 84, 83,
         237, 163, 210, 66, 34, 140, 192, 251, 98, 166, 145, 195, 245, 35, 254, 190, 229, 70, 14, 21, 245, 32, 14, 145,
         27, 151, 6, 43, 154, 205, 10, 91, 151, 60, 229, 182, 26, 188, 125, 81, 160, 163, 207, 130, 19, 22, 144, 144,
         124, 173, 222, 182, 135, 239, 83, 56, 250, 207, 186, 211, 238, 53, 103, 198, 56, 67, 145, 218, 190, 192, 235,
         210, 103, 131, 231, 18, 156, 113, 172, 180, 93, 155, 219, 96, 41, 176, 29, 167, 33, 158, 1, 13, 137, 166, 13,
         148, 195, 115, 121, 129, 189, 232, 133, 94, 41, 78, 195, 120, 91, 187, 114, 187, 153, 30, 51, 223, 142, 239,
         127, 105, 200, 47, 149, 88, 65, 223, 1, 4, 46, 203, 181, 6, 38, 237, 131, 167, 107, 60, 241, 161, 110, 221,
         175, 181, 236, 90, 226, 96, 22, 113, 30, 135, 136, 212, 26, 111, 131, 31, 187, 131, 106, 71, 91, 235, 254, 43,
         8, 52, 166, 83, 62, 151, 36, 29, 250, 97, 202, 131, 236, 159, 172, 40, 21, 61, 192, 62, 173, 26, 191, 168, 121,
         115, 227, 37, 198, 87, 235, 204, 51, 45, 220, 155, 84, 104, 50, 37, 212, 59, 175, 177, 104, 156, 119, 110, 195,
         202, 217, 188, 160, 122, 51, 180, 239, 20, 133, 232, 58, 235, 166, 68, 38, 209, 4, 187, 209, 41, 133, 28, 230,
         60, 234, 69, 194, 213, 214, 14, 206, 241, 60, 239, 167, 126, 216, 175, 184, 138, 229, 125, 254, 30, 50, 122,
         24, 4, 150, 33, 139, 127, 65, 58, 104, 102, 80, 76, 37, 29, 25, 65, 14, 61, 58, 101, 30, 94, 205, 242, 78, 63,
         124, 163, 60, 45, 85, 0, 18, 78, 74, 215, 49, 147, 80, 138, 185, 30, 43, 169, 157, 223, 169, 77, 131, 97, 151,
         75, 147, 251, 99, 23, 251, 32, 19, 122, 166, 209, 129, 120, 90, 204, 165, 28, 51, 79, 104, 19, 31, 75, 111,
         167, 37, 201, 35, 248, 120, 215, 234, 80, 82, 255, 2, 92, 64, 105, 3, 93, 22, 39, 1, 139, 231, 71, 46, 214, 24,
         67, 22, 230, 3, 213, 188, 20, 110, 180, 122, 237, 48, 132, 184, 238, 205, 40, 177, 198, 29, 201, 88, 100, 102,
         253, 178, 56, 201, 223, 156, 105, 251, 137, 234, 121, 171, 236, 154, 232, 228, 203, 35, 131, 230, 83, 185, 250,
         68, 200, 192, 93, 101, 223, 191, 77, 130, 122, 205, 18, 100, 135, 199, 68, 22, 236, 63, 81, 2, 154, 210, 222,
         127, 18, 113, 32, 114, 18, 114, 205, 1, 140, 82, 178, 180, 226, 71, 165, 91, 57, 246, 111, 169, 97, 45, 194,
         116, 127, 232, 124, 11, 69, 71, 17, 26, 4, 50, 241, 18, 39, 116, 81, 70, 72, 109, 26, 134, 206, 15, 241, 49,
         64, 97, 16, 133, 176, 96, 247, 184, 228, 238, 189, 177, 80, 103, 73, 2, 102, 232, 152, 93, 2, 15, 190, 127,
         157, 39, 138, 91, 13, 150, 252, 49, 193, 212, 145, 209, 180, 21, 88, 140, 233, 8, 113, 236, 2, 118, 141, 204,
         110, 209, 36, 229, 212, 149, 76, 110, 57, 166, 196, 22, 16, 207, 98, 77, 40, 156, 117, 192, 120, 203, 174, 49,
         251, 25, 197, 140, 9, 156, 203, 37, 21, 76, 100, 184, 201, 240, 36, 214, 236, 38, 183, 167, 27, 125, 150, 245,
         186, 248, 163, 192, 236, 107, 237, 104, 31, 0, 46, 231, 137, 38, 161, 73, 44, 235, 239, 187, 145, 212, 110, 84,
         37, 159, 51, 155, 137, 197, 175, 118, 225, 142, 77, 36, 71, 198, 132, 27, 209, 207, 168, 57, 70, 11, 120, 22,
         115, 96, 201, 160, 229, 95, 248, 182, 43, 24, 60, 102, 119, 13, 159, 30, 111, 254, 195, 65, 97, 111, 161, 140,
         45, 160, 87, 106, 195, 50, 131, 54, 126, 60, 232, 29, 54, 76, 68, 99, 45, 107, 56, 238, 187, 148, 246, 83, 42,
         69, 225, 248, 162, 17, 116, 117, 47, 249, 148, 150, 32, 158, 137, 110, 3, 218, 80, 13, 121, 22, 227, 113, 241,
         154, 238, 191, 10, 247, 126, 59, 232, 251, 162, 49, 151, 109, 18, 204, 1, 101, 173, 129, 112, 236, 75, 73, 214,
         98, 211, 216, 228, 4, 100, 67, 114, 143, 62, 212, 214, 124, 167, 189, 136, 161, 228, 56, 77, 165, 76, 222, 111,
         138, 184, 163, 98, 113, 103, 19, 74, 59, 233, 199, 242, 151, 129, 51, 15, 60, 102, 237, 134, 205, 1, 14, 212,
         57, 13, 167, 193, 171, 80, 133, 193, 46, 186, 251, 157, 222, 169, 201, 160, 44, 185, 123, 129, 215, 72, 251,
         250, 211, 242, 92, 83, 142, 98, 116, 189, 184, 95, 167, 138, 238, 125, 169, 137, 124, 60, 33, 234, 161, 206,
         143, 15, 31, 180, 54, 185, 130, 77, 252, 237, 37, 180, 218, 240, 17, 43, 189, 184, 238, 234, 154, 166, 68, 204,
         164, 209, 72, 212, 17, 24, 123, 46, 117, 132, 87, 125, 27, 204, 190, 12, 187, 85, 202, 159, 86, 41, 205, 52,
         238, 208, 88, 122, 46, 139, 252, 72, 163, 162, 156, 125, 91, 154)
xmm = (0, 1, 0, -1, 1, 0, -1, 0)
# 在代码的数据段中找到xmm
mem = np.array(list(range(100)))
# mem 不能是2维数组(考虑为负)


def decrypt():
    d1 = 0
    d0 = 0
    c1 = 0
    c0 = 0
    bf = list(range(4))
    wf = list(range(4))
    for i in range(1000):
        b = table[i]

        for k in range(4):
            bf[k] = (b >> 2*k) & 3
        for k in range(4):
            if bf[k] < 2:
                wf[k] = 1 - bf[k]
            else:
                wf[k] = 5 - bf[k]
        # 计算每个w
        for j in range(3, -1, -1):
            w = wf[j]
            print(xmm[2 * w])
            print(xmm[2 * w + 1])
            c1 = d1
            c0 = d0
            d1 = c1 - xmm[2 * w]
            d0 = c0 - xmm[2 * w + 1]
            temp = mem[c1 * 10 + c0]
            mem[c1 * 10 + c0] = mem[d1 * 10 + d0]
            mem[d1 * 10 + d0] = temp


def num2str(num):
    """
    convert a number to a string
    :
    0x12 --> "BC"
    """
    lo = num % 0x10
    h = int((num - lo) / 0x10)
    t1 = chr(h + 65)
    t0 = chr(lo + 65)
    return t1+t0


decrypt()
print(mem.flatten())
li = list(mem.flatten())
flag = ""
for qwq in li:
    flag += num2str(qwq)
print(flag)
View Flag Code

 

有一个小插曲就是这个脚本的num2str函数一不小心写错了:

1 def num2str(num):
2     lo = num % 10
3     h = int((num - lo) / 10)
4     t1 = chr(h + 65)
5     t0 = chr(lo + 65)
6     return t1+t0
View Wrong Function

导致验证flag错误,找错误浪费了一段时间

 

 内存中的数据不是0到99

qwq

(编程能力不足,有待训练啊qwq)

 

不管怎么样还是成功了……

 

 

 

 

 

 (我的分析过程有很多不足,还请各位dalao多多指点)

posted @ 2019-10-22 14:17  树行云  阅读(324)  评论(0编辑  收藏  举报