吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 5537|回复: 41
收起左侧

[CTF] 学破解第111天,《攻防世界reverse练习区ReverseMe-120》分析

[复制链接]
小菜鸟一枚 发表于 2020-7-4 16:13

学破解第111天,《攻防世界reverse练习区ReverseMe-120》分析

前言:
  一直对黑客充满了好奇,觉得黑客神秘,强大,无所不能,来论坛两年多了,天天看各位大佬发帖,自己只能做一个伸手党。也看了官方的入门视频教程,奈何自己基础太差,看不懂。自我反思之下,决定从今天(2019年6月17日)开始定下心来,从简单的基础教程开始学习,希望能从照抄照搬,到能独立分析,能独立破解。
不知不觉学习了好几个月,发现自己离了教程什么都不会,不懂算法,不懂编程。随着破解学习的深入,楼主这个半吊子迷失了自我,日渐沉迷水贴装X,不能自拔。
==========申明:从第71天楼主开始水贴装X,帖子不再具有连续性,仅供参考,后续帖子为楼主YY专用贴!!!==========

立帖为证!--------记录学习的点点滴滴

0x1下载程序

  1.首先查壳,显示Microsoft Visual C++ v.12 - 2013 ( E8 ),无壳。

  2.运行程序看看,随便输入信息,然后提示错误!
1.png

0x2调试分析

  1.丢进吾爱的OD跑起来,搜索字符串,看到提示信息

00401190  /$  55            push ebp
00401191  |.  8BEC          mov ebp,esp
00401193  |.  81EC CC000000 sub esp,0xCC
00401199  |.  68 C04E4100   push ReverseM.00414EC0                   ;  please input your flah:
0040119E  |.  E8 24010000   call ReverseM.004012C7
004011A3  |.  6A 63         push 0x63
004011A5  |.  8D85 35FFFFFF lea eax,dword ptr ss:[ebp-0xCB]
004011AB  |.  C685 34FFFFFF>mov byte ptr ss:[ebp-0xCC],0x0
004011B2  |.  6A 00         push 0x0
004011B4  |.  50            push eax
004011B5  |.  E8 E6460000   call ReverseM.004058A0
004011BA  |.  8D85 34FFFFFF lea eax,[local.51]
004011C0  |.  50            push eax
004011C1  |.  68 D84E4100   push ReverseM.00414ED8                   ;  %s

  2.很好,定位到关键函数00401190了,去IDA中F5一下

int sub_401190()
{
  unsigned int v0; // edx@1
  unsigned int v1; // ecx@1
  __m128i v2; // xmm1@3
  unsigned int v3; // esi@3
  const __m128i *v4; // eax@3
  __m128i v5; // xmm0@4
  int v6; // eax@7
  char v8; // [sp+0h] [bp-CCh]@1
  char v9; // [sp+1h] [bp-CBh]@1
  char v10; // [sp+64h] [bp-68h]@1
  char v11; // [sp+65h] [bp-67h]@1
  unsigned int v12; // [sp+C8h] [bp-4h]@1

  sub_4012C7("please input your flah:", v8);
  v8 = 0;
  memset(&v9, 0, 0x63u);
  sub_401376("%s", (unsigned int)&v8);
  v10 = 0;
  memset(&v11, 0, 0x63u);
  sub_401000(&v8, strlen(&v8));
  v0 = v12;
  v1 = 0;
  if ( v12 )
  {
    if ( v12 >= 0x10 )
    {
      v2 = _mm_load_si128((const __m128i *)&xmmword_414F20);
      v3 = v12 - (v12 & 0xF);
      v4 = (const __m128i *)&v10;
      do
      {
        v5 = _mm_loadu_si128(v4);
        v1 += 16;
        ++v4;
        _mm_storeu_si128((__m128i *)&v4[-1], _mm_xor_si128(v5, v2));
      }
      while ( v1 < v3 );
    }
    for ( ; v1 < v0; ++v1 )
      *(&v10 + v1) ^= 0x25u;
  }
  v6 = strcmp(&v10, "you_know_how_to_remove_junk_code");
  if ( v6 )
    v6 = -(v6 < 0) | 1;
  if ( v6 )
    sub_4012C7("wrong\n", v8);
  else
    sub_4012C7("correct\n", v8);
  sub_401416("pause");
  return 0;
}

  3.看看跳向失败的代码

if ( v6 )
    sub_4012C7("wrong\n", v8);
  else
    sub_4012C7("correct\n", v8);
  sub_401416("pause");
  return 0;

也就是说v6为0,才会成功,在上面是

  v6 = strcmp(&v10, "you_know_how_to_remove_junk_code");
  if ( v6 )
    v6 = -(v6 < 0) | 1;

也就说v10等于you_know_how_to_remove_junk_code,v6就会等于0,然后下面两行明显是垃圾代码,而v10定义为0。

  4.那么就只剩下下面这些代码了

if ( v12 )
  {
    if ( v12 >= 0x10 )
    {
      v2 = _mm_load_si128((const __m128i *)&xmmword_414F20);
      v3 = v12 - (v12 & 0xF);
      v4 = (const __m128i *)&v10;
      do
      {
        v5 = _mm_loadu_si128(v4);
        v1 += 16;
        ++v4;
        _mm_storeu_si128((__m128i *)&v4[-1], _mm_xor_si128(v5, v2));
      }
      while ( v1 < v3 );
    }
    for ( ; v1 < v0; ++v1 )
      *(&v10 + v1) ^= 0x25u;
  }

改变v10的里面内容的地方在for循环里面,不断将自身异或0x25,得到加密后的字符串,上面那段算法我还不能一下子看出来,接下来换成OD继续调试。

  5.随便输入01234567890进行调试

004011C1  |.  68 D84E4100   push ReverseM.00414ED8                   ;  %s
004011C6  |.  E8 AB010000   call ReverseM.00401376                   ;  输入01234567890
004011CB  |.  6A 63         push 0x63
004011CD  |.  8D45 99       lea eax,dword ptr ss:[ebp-0x67]
004011D0  |.  C645 98 00    mov byte ptr ss:[ebp-0x68],0x0
004011D4  |.  6A 00         push 0x0
004011D6  |.  50            push eax
004011D7  |.  E8 C4460000   call ReverseM.004058A0
004011DC  |.  8D8D 34FFFFFF lea ecx,[local.51]                       ;  取出输入的字符串存入ecx
004011E2  |.  83C4 24       add esp,0x24                             ;  平衡堆栈
004011E5  |.  8D51 01       lea edx,dword ptr ds:[ecx+0x1]           ;  存入到edx
004011E8  |>  8A01          /mov al,byte ptr ds:[ecx]                ;  计算字符串长度
004011EA  |.  41            |inc ecx                                 ;  ReverseM.00414EDC
004011EB  |.  84C0          |test al,al
004011ED  |.^ 75 F9         \jnz short ReverseM.004011E8
004011EF  |.  2BCA          sub ecx,edx                              ;  将字符串长度0xB存入ecx
004011F1  |.  8D85 34FFFFFF lea eax,[local.51]                       ;  将字符串存入eax
004011F7  |.  51            push ecx                                 ;  ReverseM.00414EDC
004011F8  |.  50            push eax
004011F9  |.  8D55 FC       lea edx,[local.1]
004011FC  |.  8D4D 98       lea ecx,[local.26]
004011FF  |.  E8 FCFDFFFF   call ReverseM.00401000                   ;  这个call就是加密函数
00401204  |.  8B55 FC       mov edx,[local.1]                        ;  edx的值为6
00401207  |.  83C4 08       add esp,0x8                              ;  平衡堆栈
0040120A  |.  33C9          xor ecx,ecx                              ;  清空ecx
0040120C  |.  85D2          test edx,edx                             ;  判断edx是否为0
0040120E  |.  74 4A         je short ReverseM.0040125A
00401210  |.  83FA 10       cmp edx,0x10                             ;  判断edx是不是小于10
00401213  |.  72 33         jb short ReverseM.00401248               ;  这里手动改下C标志,让跳转不实现,方便我下一步分析
00401215  |.  66:0F6F0D 204>movq mm1,qword ptr ds:[0x414F20]         ;  %%%%%%%%%%%%%%%%H
0040121D  |.  8BC2          mov eax,edx                              ;  将edx的值6给了ecx
0040121F  |.  56            push esi
00401220  |.  83E0 0F       and eax,0xF                              ;  将edx与00001111进行与运算
00401223  |.  8BF2          mov esi,edx
00401225  |.  2BF0          sub esi,eax                              ;  edx,ecx都为6,这样减esi肯定为0
00401227  |.  8D45 98       lea eax,[local.26]
0040122A  |.  8D9B 00000000 lea ebx,dword ptr ds:[ebx]
00401230  |>  f30f6f00      /movdqu xmm0,dqword ptr ds:[eax]
00401234  |.  83C1 10       |add ecx,0x10
00401237  |.  8D40 10       |lea eax,dword ptr ds:[eax+0x10]
0040123A  |.  66:0FEFC1     |pxor mm0,mm1
0040123E  |.  f30f7f40 f0   |movdqu dqword ptr ds:[eax-0x10],xmm0
00401243  |.  3BCE          |cmp ecx,esi
00401245  |.^ 72 E9         \jb short ReverseM.00401230
00401247  |.  5E            pop esi
00401248  |>  3BCA          cmp ecx,edx                              ;  这里ecx是0x10也就是16,与6相比,大于等于跳转
0040124A  |.  73 0E         jnb short ReverseM.0040125A
0040124C  |.  8D6424 00     lea esp,dword ptr ss:[esp]
00401250  |>  80740D 98 25  /xor byte ptr ss:[ebp+ecx-0x68],0x25
00401255  |.  41            |inc ecx                                 ;  ReverseM.00414EDC
00401256  |.  3BCA          |cmp ecx,edx
00401258  |.^ 72 F6         \jb short ReverseM.00401250
0040125A  |>  B9 DC4E4100   mov ecx,ReverseM.00414EDC                ;  you_know_how_to_remove_junk_code
0040125F  |.  8D45 98       lea eax,[local.26]                       ;  典型的strcmp函数
00401262  |>  8A10          /mov dl,byte ptr ds:[eax]
00401264  |.  3A11          |cmp dl,byte ptr ds:[ecx]
00401266  |.  75 1A         |jnz short ReverseM.00401282
00401268  |.  84D2          |test dl,dl
0040126A  |.  74 12         |je short ReverseM.0040127E
0040126C  |.  8A50 01       |mov dl,byte ptr ds:[eax+0x1]
0040126F  |.  3A51 01       |cmp dl,byte ptr ds:[ecx+0x1]
00401272  |.  75 0E         |jnz short ReverseM.00401282
00401274  |.  83C0 02       |add eax,0x2
00401277  |.  83C1 02       |add ecx,0x2
0040127A  |.  84D2          |test dl,dl
0040127C  |.^ 75 E4         \jnz short ReverseM.00401262
0040127E  |>  33C0          xor eax,eax
00401280  |.  EB 05         jmp short ReverseM.00401287

通过以上分析和IDA的最照,除了加密call以外,基本都了解了。

  6.接下来就要去里面瞧一瞧我们输入的字符串到底怎么被处理的。

00401000  /$  55            push ebp
00401001  |.  8BEC          mov ebp,esp
00401003  |.  83EC 0C       sub esp,0xC                              ;  分配3个局部变量
00401006  |.  53            push ebx
00401007  |.  56            push esi
00401008  |.  8B75 0C       mov esi,[arg.2]                          ;  arg2保存的是字符串到长度0xB,也就是11
0040100B  |.  33DB          xor ebx,ebx                              ;  清空ebx,后面是花指令
0040100D  |.  894D F4       mov [local.3],ecx
00401010  |.  33C0          xor eax,eax
00401012  |.  33C9          xor ecx,ecx
00401014  |.  8955 F8       mov [local.2],edx
00401017  |.  894D FC       mov [local.1],ecx
0040101A  |.  57            push edi                                 ;  上面这些是花指令???
0040101B  |.  85F6          test esi,esi                             ;  esi为0就跳转
0040101D  |.  0F84 3F010000 je ReverseM.00401162
00401023  |.  8B7D 08       mov edi,[arg.1]                          ;  arg1使我们输入到字符串
00401026  |>  33D2          /xor edx,edx                             ;  清空edx
00401028  |.  3BC6          |cmp eax,esi                             ;  比较eax和esi的值
0040102A  |.  73 12         |jnb short ReverseM.0040103E             ;  不小于0跳转
0040102C  |.  8D6424 00     |lea esp,dword ptr ss:[esp]              ;  取出esp寄存器中的值给esp
00401030  |>  803C38 20     |/cmp byte ptr ds:[eax+edi],0x20         ;  判断edx+edi等不等于0x20,也就是32
00401034  |.  75 06         ||jnz short ReverseM.0040103C
00401036  |.  40            ||inc eax
00401037  |.  42            ||inc edx
00401038  |.  3BC6          ||cmp eax,esi
0040103A  |.^ 72 F4         |\jb short ReverseM.00401030
0040103C  |>  3BC6          |cmp eax,esi
0040103E  |>  74 72         |je short ReverseM.004010B2
00401040  |.  8BCE          |mov ecx,esi                             ;  ecx获得字符串长度
00401042  |.  2BC8          |sub ecx,eax                             ;  ecx减去eax
00401044  |.  83F9 02       |cmp ecx,0x2                             ;  eax和2比较
00401047  |.  72 0D         |jb short ReverseM.00401056              ;  小于就跳走
00401049  |.  803C38 0D     |cmp byte ptr ds:[eax+edi],0xD           ;  不相等就跳走
0040104D  |.  75 07         |jnz short ReverseM.00401056
0040104F  |.  807C38 01 0A  |cmp byte ptr ds:[eax+edi+0x1],0xA
00401054  |.  74 50         |je short ReverseM.004010A6
00401056  |>  8A0C38        |mov cl,byte ptr ds:[eax+edi]            ;  再将字符串第一个字符给ecx的低8位
00401059  |.  80F9 0A       |cmp cl,0xA
0040105C  |.  74 48         |je short ReverseM.004010A6
0040105E  |.  85D2          |test edx,edx                            ;  edx是0,不跳走
00401060  |.  0F85 05010000 |jnz ReverseM.0040116B
00401066  |.  80F9 3D       |cmp cl,0x3D                             ;  0x3d是=
00401069  |.  75 0A         |jnz short ReverseM.00401075             ;  不相等跳走
0040106B  |.  43            |inc ebx
0040106C  |.  83FB 02       |cmp ebx,0x2
0040106F  |.  0F87 F6000000 |ja ReverseM.0040116B
00401075  |>  80F9 7F       |cmp cl,0x7F                             ;  0x7F是127
00401078  |.  0F87 ED000000 |ja ReverseM.0040116B                    ;  大于就跳走
0040107E  |.  0FB6C9        |movzx ecx,cl                            ;  将cl给ecx,字符0
00401081  |.  8A89 404E4100 |mov cl,byte ptr ds:[ecx+0x414E40]       ;  将0x34赋值给cl
00401087  |.  80F9 7F       |cmp cl,0x7F
0040108A  |.  0F84 DB000000 |je ReverseM.0040116B                    ;  同样的比较
00401090  |.  80F9 40       |cmp cl,0x40
00401093  |.  73 08         |jnb short ReverseM.0040109D             ;  不小于0跳转
00401095  |.  85DB          |test ebx,ebx                            ;  ebx之前被清空了,这还是0
00401097  |.  0F85 CE000000 |jnz ReverseM.0040116B
0040109D  |>  8B4D FC       |mov ecx,[local.1]
004010A0  |.  41            |inc ecx                                 ;  ecx+1
004010A1  |.  894D FC       |mov [local.1],ecx                       ;  再将ecx给local1,也就是说ecx每次加1
004010A4  |.  EB 03         |jmp short ReverseM.004010A9
004010A6  |>  8B4D FC       |mov ecx,[local.1]
004010A9  |>  40            |inc eax                                 ;  eax每次也是加1
004010AA  |.  3BC6          |cmp eax,esi                             ;  eax此时为1,还是小于0
004010AC  |.^ 0F82 74FFFFFF \jb ReverseM.00401026                    ;  这里小于0跳转
004010B2  |>  85C9          test ecx,ecx
004010B4  |.  0F84 A8000000 je ReverseM.00401162                     ;  相等,这里不会跳走
004010BA  |.  8B75 F4       mov esi,[local.3]
004010BD  |.  8D0C49        lea ecx,dword ptr ds:[ecx+ecx*2]
004010C0  |.  8D0C4D 070000>lea ecx,dword ptr ds:[ecx*2+0x7]         ;  这是在干嘛,ecx的值为0x49
004010C7  |.  C1E9 03       shr ecx,0x3                              ;  右移3位,值为9
004010CA  |.  2BCB          sub ecx,ebx
004010CC  |.  85F6          test esi,esi
004010CE  |.  0F84 A3000000 je ReverseM.00401177
004010D4  |.  8B55 F8       mov edx,[local.2]
004010D7  |.  390A          cmp dword ptr ds:[edx],ecx
004010D9  |.  0F82 98000000 jb ReverseM.00401177                     ;  不跳走
004010DF  |.  33C9          xor ecx,ecx
004010E1  |.  C745 FC 03000>mov [local.1],0x3                        ;  将0x3给回去
004010E8  |.  33DB          xor ebx,ebx
004010EA  |.  894D 0C       mov [arg.2],ecx                          ;  ecx清0
004010ED  |.  85C0          test eax,eax
004010EF  |.  74 69         je short ReverseM.0040115A
004010F1  |>  8A0F          /mov cl,byte ptr ds:[edi]                ;  下面这一段就是在for循环处理输入的字符串了
004010F3  |.  80F9 0D       |cmp cl,0xD
004010F6  |.  74 5E         |je short ReverseM.00401156
004010F8  |.  80F9 0A       |cmp cl,0xA
004010FB  |.  74 59         |je short ReverseM.00401156
004010FD  |.  80F9 20       |cmp cl,0x20
00401100  |.  74 54         |je short ReverseM.00401156
00401102  |.  0FB6C9        |movzx ecx,cl
00401105  |.  8A91 404E4100 |mov dl,byte ptr ds:[ecx+0x414E40]       ;  读取4给dl
0040110B  |.  33C9          |xor ecx,ecx                             ;  清空ecx
0040110D  |.  80FA 40       |cmp dl,0x40
00401110  |.  0F94C1        |sete cl                                 ;  设置为false
00401113  |.  C1E3 06       |shl ebx,0x6                             ;  将ebx左移6位
00401116  |.  294D FC       |sub [local.1],ecx
00401119  |.  0FB6CA        |movzx ecx,dl                            ;  将dl的值4给ecx
0040111C  |.  8B55 0C       |mov edx,[arg.2]                         ;  arg2此时是0
0040111F  |.  83E1 3F       |and ecx,0x3F                            ;  0x3F是?
00401122  |.  42            |inc edx                                 ;  edx+1
00401123  |.  0BD9          |or ebx,ecx                              ;  ebx和ecx或运算
00401125  |.  8955 0C       |mov [arg.2],edx
00401128  |.  83FA 04       |cmp edx,0x4
0040112B  |.  75 29         |jnz short ReverseM.00401156             ;  跳走
0040112D  |.  8B55 FC       |mov edx,[local.1]
00401130  |.  33C9          |xor ecx,ecx
00401132  |.  894D 0C       |mov [arg.2],ecx
00401135  |.  85D2          |test edx,edx
00401137  |.  74 08         |je short ReverseM.00401141
00401139  |.  8BCB          |mov ecx,ebx
0040113B  |.  C1E9 10       |shr ecx,0x10
0040113E  |.  880E          |mov byte ptr ds:[esi],cl
00401140  |.  46            |inc esi
00401141  |>  83FA 01       |cmp edx,0x1
00401144  |.  76 08         |jbe short ReverseM.0040114E
00401146  |.  8BCB          |mov ecx,ebx
00401148  |.  C1E9 08       |shr ecx,0x8
0040114B  |.  880E          |mov byte ptr ds:[esi],cl
0040114D  |.  46            |inc esi
0040114E  |>  83FA 02       |cmp edx,0x2
00401151  |.  76 03         |jbe short ReverseM.00401156
00401153  |.  881E          |mov byte ptr ds:[esi],bl
00401155  |.  46            |inc esi
00401156  |>  47            |inc edi                                 ;  edi的值+1
00401157  |.  48            |dec eax
00401158  |.^ 75 97         \jnz short ReverseM.004010F1             ;  eax的值减1
0040115A  |>  8B45 F8       mov eax,[local.2]
0040115D  |.  2B75 F4       sub esi,[local.3]
00401160  |.  8930          mov dword ptr ds:[eax],esi
00401162  |>  5F            pop edi
00401163  |.  5E            pop esi
00401164  |.  33C0          xor eax,eax
00401166  |.  5B            pop ebx
00401167  |.  8BE5          mov esp,ebp
00401169  |.  5D            pop ebp
0040116A  |.  C3            retn

垃圾代码太多,分析的是不是有点晕头转向。

  7.再来IDA,看看401000函数

signed int __usercall sub_401000@<eax>(unsigned int *a1@<edx>, _BYTE *a2@<ecx>, char *a3, unsigned int a4)
{
  int v4; // ebx@1
  unsigned int v5; // eax@1
  int v6; // ecx@1
  char *v7; // edi@2
  int v8; // edx@3
  bool v9; // zf@3
  unsigned __int8 v10; // cl@11
  char v11; // cl@16
  _BYTE *v12; // esi@23
  unsigned int v13; // ecx@23
  unsigned int v14; // ebx@25
  unsigned __int8 v15; // cl@26
  char v16; // dl@29
  _BYTE *v18; // [sp+Ch] [bp-Ch]@1
  unsigned int *v19; // [sp+10h] [bp-8h]@1
  int v20; // [sp+14h] [bp-4h]@1
  unsigned int v21; // [sp+14h] [bp-4h]@25
  int i; // [sp+24h] [bp+Ch]@25

  v4 = 0;
  v18 = a2;
  v5 = 0;
  v6 = 0;
  v19 = a1;
  v20 = 0;
  if ( !a4 )
    return 0;
  v7 = a3;
  do
  {
    v8 = 0;
    v9 = v5 == a4;
    if ( v5 < a4 )
    {
      do
      {
        if ( a3[v5] != 32 )
          break;
        ++v5;
        ++v8;
      }
      while ( v5 < a4 );
      v9 = v5 == a4;
    }
    if ( v9 )
      break;
    if ( a4 - v5 >= 2 && a3[v5] == 13 && a3[v5 + 1] == 10 || (v10 = a3[v5], v10 == 10) )
    {
      v6 = v20;
    }
    else
    {
      if ( v8 )
        return -44;
      if ( v10 == 61 && (unsigned int)++v4 > 2 )
        return -44;
      if ( v10 > 0x7Fu )
        return -44;
      v11 = byte_414E40[v10];
      if ( v11 == 127 || (unsigned __int8)v11 < 0x40u && v4 )
        return -44;
      v6 = v20++ + 1;
    }
    ++v5;
  }
  while ( v5 < a4 );
  if ( !v6 )
    return 0;
  v12 = v18;
  v13 = ((unsigned int)(6 * v6 + 7) >> 3) - v4;
  if ( v18 && *v19 >= v13 )
  {
    v21 = 3;
    v14 = 0;
    for ( i = 0; v5; --v5 )
    {
      v15 = *v7;
      if ( *v7 != 13 && v15 != 10 && v15 != 32 )
      {
        v16 = byte_414E40[v15];
        v21 -= v16 == 64;
        v14 = v16 & 0x3F | (v14 << 6);
        if ( ++i == 4 )
        {
          i = 0;
          if ( v21 )
            *v12++ = v14 >> 16;
          if ( v21 > 1 )
            *v12++ = BYTE1(v14);
          if ( v21 > 2 )
            *v12++ = v14;
        }
      }
      ++v7;
    }
    *v19 = v12 - v18;
    return 0;
  }
  *v19 = v13;
  return -42;
}

传递了四个参数,结合前面OD的分析可知a3是我们输入的字符串,a4是字符串的长度,a2是0012FF78-0x4,a1是0012FF78-0x68,v18 = a2;v19 = a1;v7 = a3。

  8.再来看这些值用在哪里,做了什么。

  v13 = ((unsigned int)(6 * v6 + 7) >> 3) - v4;
  if ( v18 && *v19 >= v13 )
  {
    v21 = 3;
    v14 = 0;
    for ( i = 0; v5; --v5 )//v5是字符串的长度,一直-1操作
    {
      v15 = *v7;//注意了v7这个字符串的第一个字符给了v15
      if ( *v7 != 13 && v15 != 10 && v15 != 32 )//这是在干啥?
      {
        v16 = byte_414E40[v15];//一串类似密码表的东西,以0x7F开头,字符不可见>?456789:;<=@',0
        v21 -= v16 == 64;//v16是密码表中第v15+1个字符,64是@符号
        v14 = v16 & 0x3F | (v14 << 6);取v16后六位,v14的前两位给v14
        if ( ++i == 4 )//判断i等不等于4,同时i++,每次取4个字符,然后依次赋值给v12的三个字符
        {
          i = 0;//每循环4次,i的值清零
          if ( v21 )//如果v21 = 1
            *v12++ = v14 >> 16;//将v14右移16位赋值给*v12,同时v12指针右移一位
          if ( v21 > 1 )//如果v21 > 1
            *v12++ = BYTE1(v14);//直接将V14给*v12,同时v12指针右移一位
          if ( v21 > 2 )//如果v21 > 2
            *v12++ = v14;直接将v14的值给*v12,同时v12指针右移一位
        }
      }
      ++v7;//字符串指针右移一位
    }
    *v19 = v12 - v18;
    return 0;
  }

  9.这怎么特别的像base64解密的过程呢?

0x3尝试编写算法

  1.思路,我输入的字符串通过base64解密,然后异或0x25等于"you_know_how_to_remove_junk_code"这个字符串,就说明我输入的字符串是正确的flag,那么我可以反其道而行之,输入这个比较的字符串,然后异或25,接着进行base64加密不就可以得到flag了吗?

  2.编写程序,成功得到flag:XEpQek5LSlJ6TUpSelFKeldASEpTQHpPUEtOekZKQUA=,具体base64编码解码实现函数:https://www.52pojie.cn/thread-1212431-1-1.html

int main()
{
    char str1[100] = "you_know_how_to_remove_junk_code";
    char str2[100];

    for (int i = 0; i < strlen(str1); i++)
    {
        *(str1 + i) ^= 0x25;
    }

    encodeBase64(str1, strlen(str1), str2, strlen(str2));
    cout << str2 << endl;

    system("pause");
    return 0;
}

  3.IDA F5的效果不太好,差点错过了401000函数,最后还是贴一张成功图,高兴一下。
2.png

0x4总结

  1.论坛编辑器会自动把[i]识别成斜体,还好我用的是c++有指针可以用*操作。

  2.调试果然不能全靠IDA的F5,压根就没识别到在哪调用的401000函数,结合OD,到了调用这个函数,然后再去IDA分析。

  3.听说IDA也能动态调试,我不会,只能碰到入栈参数和函数调用去OD中调试看,然后再回IDA分析。

  4.不懂汇编,完全不能区分哪些是垃圾指令,只能靠猜。

  5.只有了解算法的实现原理,最好能体验一把算法的实现,结合反汇编代码,才能更好的分析算法。



总结:楼主是个小菜鸟,离了教程啥都不会!

免费评分

参与人数 11威望 +1 吾爱币 +29 热心值 +11 收起 理由
dreamlivemeng + 1 + 1 谢谢@Thanks!
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
XingTiger + 1 + 1 用心讨论,共获提升!
suoai216 + 1 + 1 用心讨论,共获提升!
huangyiyi + 1 + 1 向坚持学习的学习并点赞
爱我666 + 1 + 1 谢谢@Thanks!
iYolo丶moye + 1 用心讨论,共获提升!
多凉凉 + 1 + 1 谢谢@Thanks!
∞泡泡∞ + 1 + 1 热心回复!
aoenian + 1 + 1 我也迷失在水贴不能自拔
fanweikang + 1 + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| 小菜鸟一枚 发表于 2020-7-5 12:18
1933420530 发表于 2020-7-5 12:14
膜拜大佬,能不能教我,

https://www.52pojie.cn/thread-1208234-1-1.html来,跟着我从第一天学,或者你自己搜索论坛零基础教程,选择合适自己的入门。
vrvree 发表于 2020-7-5 11:17


问一下  楼主  学破解的话   一般多少时间之内才有起色
guide 发表于 2020-7-4 16:35
ミм謌 发表于 2020-7-4 16:55
只要努力肯专一定会成功的加油!
volcanocan 发表于 2020-7-4 17:59
加油加油!!!
liu5653250 发表于 2020-7-4 19:05
厉害厉害,比我强!哈哈
小马驾到 发表于 2020-7-4 19:06
加油加油
nut1999 发表于 2020-7-4 21:05
加油,奥里给
0319yang 发表于 2020-7-4 21:34
坚持,一定胜利&#9996;
wangxd 发表于 2020-7-4 21:53
坚持,一定胜利&#9996;
liehuo2012 发表于 2020-7-4 22:08
楼主的毅力不错,继续努力吧,一定会胜利的,加油!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-4-29 15:45

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表