吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4449|回复: 30
收起左侧

[CTF] 学破解第140天,《攻防世界reverse练习区流浪者》学习

  [复制链接]
小菜鸟一枚 发表于 2021-8-21 17:14

学破解第140天,《攻防世界reverse练习区流浪者》学习

前言:
  从小学到大专(计算机网络技术专业),玩过去的,所以学习成绩惨不忍睹,什么证书也没考,直到找不到工作才后悔,不知道怎么办才好。

  2017年12月16日,通过19元注册码注册论坛账号,开始做伸手党,潜水一年多,上来就是找软件。(拿论坛高大上的软件出去装X)

  2018年8月10日,报名了华中科技大学网络教育本科(计算机科学与技术专业)2018级秋季。(开始提升学历)

  2019年6月17日,不愿再做小菜鸟一枚,开始零基础学习破解。(感谢小糊涂虫大哥在我刚开始学习脱壳时,录制视频解答我的问题)

  2020年7月7日,感谢H大对我的鼓励,拥有了第一篇获得优秀的文章。(接下来希望学习逆向,逆天改命)

  2021年8月11日,华科学位英语2次不过,仅取得了毕业证书,学业提升失败,开始琢磨考注册类和职称类证书,谋求涨薪

  坛友们,年轻就是资本,和我一起逆天改命吧,我的学习过程全部记录及学习资源:https://www.52pojie.cn/thread-1278021-1-1.html
立帖为证!--------记录学习的点点滴滴

0x1下载文件

  1.下载CM,是一个压缩包,解压后发现是个exe文件。

  2.通过图标来看是一个MFC程序

  3.使用exeinfo工具查壳:
https://z3.ax1x.com/2021/08/21/fvtLjJ.png

  4.根据上述信息,知道这是一个32位无壳的MFC程序,可以使用OD和IDA来调试。

0x2寻找爆破点

  1.对于window程序不像控制台程序,IDA找到main函数,一层层看就完了,这找到winmain函数,也不知道怎么找到逻辑,还是和我没有window编程基础有关。

  2.还是先用OD找到爆破点,定位关键函数再去看代码对比。

  2.那么我们OD载入程序,F9运行起来,随便输入123456,点击验证,弹出错误提示,再去401000处搜索一下字符串:
https://z3.ax1x.com/2021/08/21/fvUoSU.png

  3.根据上图中错误提示和搜索到的字符串,定位错误弹窗的地方:

004017B0  /$  55            push ebp
004017B1  |.  8BEC          mov ebp,esp
004017B3  |.  83EC 44       sub esp,0x44
004017B6  |.  53            push ebx
004017B7  |.  56            push esi
004017B8  |.  57            push edi
004017B9  |.  6A 00         push 0x0                                 ; /Style = MB_OK|MB_APPLMODAL
004017BB  |.  68 78354000   push cm.00403578                         ; |错了!
004017C0  |.  68 70354000   push cm.00403570                         ; |加油!
004017C5  |.  6A 00         push 0x0                                 ; |hOwner = NULL
004017C7  |.  FF15 00324000 call dword ptr ds:[<&USER32.MessageBoxA>>; \MessageBoxA

  4.通过堆栈按回车键返回调用处:

00401857  |> \8B55 FC       mov edx,[local.1]
0040185A  |.  C64415 DC 00  mov byte ptr ss:[ebp+edx-0x24],0x0
0040185F  |.  8B45 BC       mov eax,[local.17]                       ;  cm.004035C0
00401862  |.  50            push eax                                 ; /s2 = 00000001 ???
00401863  |.  8D4D DC       lea ecx,[local.9]                        ; |
00401866  |.  51            push ecx                                 ; |s1 = "KanXueCTF2019JustForhappy"
00401867  |.  E8 84070000   call <jmp.&MSVCRT.strcmp>                ; \strcmp
0040186C  |.  83C4 08       add esp,0x8
0040186F  |.  85C0          test eax,eax
00401871  |.  75 07         jnz short cm.0040187A                    ;  两个字符串不相等,就跳向失败
00401873  |.  E8 F8FEFFFF   call cm.00401770
00401878  |.  EB 05         jmp short cm.0040187F
0040187A  |>  E8 31FFFFFF   call cm.004017B0                         ;  失败弹窗函数

  5.接着去段首004017F0 处F2下上断点,重启跑过来看一看,这段汇编代码:

0040180A  |.  C745 BC C0354>mov [local.17],cm.004035C0               ;  KanXueCTF2019JustForhappy
00401811  |.  C785 50FFFFFF>mov [local.44],cm.00403580               ;  abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ

有两个可疑字符串,继续看:

0040181B  |> /8B45 FC       /mov eax,[local.1]                       ;  eax=0
0040181E  |. |8B4D 08       |mov ecx,[arg.1]                         ;  ecx=0018F700
00401821  |. |833C81 3E     |cmp dword ptr ds:[ecx+eax*4],0x3E       ;  堆栈 ds:[0018F700]=00000001
00401825  |. |7D 30         |jge short cm.00401857                   ;  大于等于62则跳转
00401827  |. |8B55 FC       |mov edx,[local.1]                       ;  edx=0
0040182A  |. |8B45 08       |mov eax,[arg.1]                         ;  eax=0018F700
0040182D  |. |833C90 00     |cmp dword ptr ds:[eax+edx*4],0x0        ;  堆栈 ds:[0018F700]=00000001
00401831  |. |7C 24         |jl short cm.00401857                    ;  小于0则跳转
00401833  |. |8B4D FC       |mov ecx,[local.1]                       ;  ecx=0
00401836  |. |8B55 08       |mov edx,[arg.1]                         ;  edx=0018F700
00401839  |. |8B048A        |mov eax,dword ptr ds:[edx+ecx*4]        ;  eax=1
0040183C  |. |8B4D FC       |mov ecx,[local.1]                       ;  ecx=0
0040183F  |. |8B95 50FFFFFF |mov edx,[local.44]                      ;  edx="abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ"
00401845  |. |8A0402        |mov al,byte ptr ds:[edx+eax]            ;  al = b
00401848  |. |88440D DC     |mov byte ptr ss:[ebp+ecx-0x24],al       ;  存入一块内存
0040184C  |. |8B4D FC       |mov ecx,[local.1]                       ;  ecx=0
0040184F  |. |83C1 01       |add ecx,0x1                             ;  ecx+1
00401852  |. |894D FC       |mov [local.1],ecx                       ;  变量1=ecx
00401855  |.^\EB C4         \jmp short cm.0040181B                   ;  开始下一轮循环

这是一个循环结构,每次我输入的处理一个我输入的变量存入某一块内存地址ebp+ecx-0x24,[ecx+eax*4]这个在学习数据结构时我们知道它大概率是数组,而且是4字节对齐的,从一个数组中取出数据al=edx+eax就是赋值的过程,a1=edx[i],i是我输入的值,并且我输入的值每一位取值必须在[0,62)这个区间。

  6.F4跳过循环,可以看到我输入的123456,变成了bcdefg:

00401862  |.  50            push eax                                 ; /s2 = "KanXueCTF2019JustForhappy"
00401863  |.  8D4D DC       lea ecx,[local.9]                        ; |
00401866  |.  51            push ecx                                 ; |s1 = "bcdefg"
00401867  |.  E8 84070000   call <jmp.&MSVCRT.strcmp>                ; \strcmp

再回过头来看看这两行的可疑的字符串:
KanXueCTF2019JustForhappy
abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ
第一个没得说,一会和我输入的字符串处理后作比较,第二个字符串我们看看,这个字符串所在的起始地址为:0x403580,再看前面赋值语句:
0040183F  |.  8B95 50FFFFFF |mov edx,[local.44]                      ;  edx="abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ"
00401845  |.  8A0402        |mov al,byte ptr ds:[edx+eax]            ;  al = b
edx的值就是0x403580,是不是一下子很清楚了,a1=arr[1]=b,a2=arr[2]=c,a1=arr[3]=c,以此类推通过替换的方式得到bcdefg。

0x3代码分析

  1.将程序用32位IDA打开,找到004017B0这个函数,打开看一看代码涨啥样:

int __cdecl sub_4017F0(int a1)
{
  int result; // eax
  char Str1[28]; // [esp+D8h] [ebp-24h] BYREF
  int v3; // [esp+F4h] [ebp-8h]
  int v4; // [esp+F8h] [ebp-4h]

  v4 = 0;
  v3 = 0;
  while ( *(int *)(a1 + 4 * v4) < 62 && *(int *)(a1 + 4 * v4) >= 0 )
  {
    Str1[v4] = aAbcdefghiabcde[*(_DWORD *)(a1 + 4 * v4)];
    ++v4;
  }
  Str1[v4] = 0;
  if ( !strcmp(Str1, "KanXueCTF2019JustForhappy") )
    result = sub_401770();
  else
    result = sub_4017B0();
  return result;
}

aAbcdefghiabcde这个数组存的就是“abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ”,上述代码反过来就是遍历这个数组中的每一个元素和KanXueCTF2019JustForhappy"相等就保存下来,逆向的代码为:

char arr[63] = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ";

while (v4 < strlen(arr))
{
        if (flag[i] == arr[v4])
        //取v4的值
}

为了循环判断,所以外层还需要加一个循环。

  2.F5反编译的代码和我分析的差不多,接下来就写代码跑flag了,等等,似乎有什么不对?我输入123456是字符,为什么加密的时候作为数字下标呢???显然前面有将字符串如何变成数字下标的函数。

004019C2  |.  52            push edx
004019C3  |.  E8 28FEFFFF   call cm.004017F0

通过OD查找调用过程,发现从004019C3这个地址调用的004017F0函数,向上翻找到段首00401890。

  3.IDA中找到这个函数,F5反编译一下:

int __thiscall sub_401890(CWnd *this)
{
  CWnd *v1; // eax
  int v2; // eax
  struct CString *v4; // [esp-4h] [ebp-C4h]
  int v5[26]; // [esp+4Ch] [ebp-74h] BYREF
  int i; // [esp+B4h] [ebp-Ch]
  char *Str; // [esp+B8h] [ebp-8h]
  CWnd *v8; // [esp+BCh] [ebp-4h]

  v8 = this;
  v4 = (CWnd *)((char *)this + 100);
  v1 = CWnd::GetDlgItem(this, 1002);
  CWnd::GetWindowTextA(v1, v4);
  v2 = sub_401A30((char *)v8 + 100);
  Str = CString::GetBuffer((CWnd *)((char *)v8 + 100), v2);
  if ( !strlen(Str) )
    return CWnd::MessageBoxA(v8, "请输入pass!", 0, 0);
  for ( i = 0; Str[i]; ++i )
  {
    if ( Str[i] > 57 || Str[i] < 48 )
    {
      if ( Str[i] > 122 || Str[i] < 97 )
      {
        if ( Str[i] > 90 || Str[i] < 65 )
          sub_4017B0();
        else
          v5[i] = Str[i] - 29;
      }
      else
      {
        v5[i] = Str[i] - 87;
      }
    }
    else
    {
      v5[i] = Str[i] - 48;
    }
  }
  return sub_4017F0(v5);
}

找到了转换的函数,这种层层嵌套读起来真是要人命,同样逆向过来,大于变成小于等于,小于变成大于等于,-变成+,得到:

if (v4 + 48 >= 48 && v4 + 48 <= 57)
{
        str[i] = v4 + 48;
}
if (v4 + 87 >= 97 && v4 + 87 <= 122)
{
        str[i] = v4 + 87;
}
if (v4 + 29 >= 65 && v4 + 29 <= 90)
{
        str[i] = v4 + 29;
}

  4.最终整理后的代码如下:

#include <iostream>
#include <thread>

using namespace std;

int main()
{
        char flag[26] = "KanXueCTF2019JustForhappy";
        char arr[63] = "abcdefghiABCDEFGHIJKLMNjklmn0123456789opqrstuvwxyzOPQRSTUVWXYZ";
        char str[26] = "";
        int i = 0, v4 = 0;

        while (i < strlen(flag)){
                while (v4 < strlen(arr))
                {
                        if (flag[i] == arr[v4]) {
                                if (v4 + 48 >= 48 && v4 + 48 <= 57)
                                {
                                        str[i] = v4 + 48;
                                }
                                if (v4 + 87 >= 97 && v4 + 87 <= 122)
                                {
                                        str[i] = v4 + 87;
                                }
                                if (v4 + 29 >= 65 && v4 + 29 <= 90)
                                {
                                        str[i] = v4 + 29;
                                }
                                i++;
                                v4=0;
                                break;
                        }
                        ++v4;
                }
        }

        cout << str << endl;

        system("pause");
}

  5.运行后得到:j0rXI4bTeustBiIGHeCF70DDM,,加上flag{}就是flag{j0rXI4bTeustBiIGHeCF70DDM},输入答案验证一下。
https://z3.ax1x.com/2021/08/21/fxpOtU.png

0x4总结

  1.通过错误提示定位关键字符串,找到关键跳,关键跳前面的一般就是算法了。
  2.分析的时候不要大意,字符串可能不只经过一次变换,对字符串变化流程加以分析。
  3.编写逆向算法时,如果看不懂原算法,那就利用程序自身算法,脑袋里一定要反过来思考,才能写出逆向程序。
  4.这道1分题花了我6个多小时,还是基础不牢固啊。

0x5参考资料

  1.无

  PS:善于总结,善于发现,找到分析问题的思路和解决问题的办法。虽然我现在还是零基础的小菜鸟一枚,也许学习逆向逆天改命我会失败,但也有着成功的可能,只要还有希望,就决不放弃!

免费评分

参与人数 18威望 +1 吾爱币 +37 热心值 +16 收起 理由
Hmily + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
ee789852 + 1 + 1 优秀的人
shiyucj + 1 + 1 我很赞同!
shakespearexzh + 1 热心回复!
don1sv + 1 + 1 太励志
SAPLU + 1 + 1 我很赞同!
hydswcxx + 2 + 1 鼓励转贴优秀软件安全工具和文档!
rigxu + 1 + 1 鼓励转贴优秀软件安全工具和文档!
海太大太深 + 1 我很赞同!
mxjxz + 1 + 1 我很赞同!
nnicetry + 1 + 1 我很赞同!
xhever + 1 + 1 谢谢@Thanks!
plasd + 1 + 1 用心讨论,共获提升!
努力加载中 + 1 + 1 我很赞同!
香芋 + 1 + 1 用心讨论,共获提升!
OYyunshen + 1 + 1 热心回复!
维多利加 + 1 + 1 热心回复!
Bizhi-1024 + 1 用心讨论,共获提升!

查看全部评分

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

破解粉丝 发表于 2021-8-21 18:04
支持你这种坚持学习的精神!不管干任何事情都不能缺这种持之以恒的精神!给你点赞!!!!
骄阳似我 发表于 2021-8-21 18:22
真的从小菜鸟变成大佬了。我从菜鸟变成了菜鸡
DrCatcher 发表于 2021-8-21 18:46
网络教育本科是不是函授?不用到学校坐到教室上课的那种?
kkyy123 发表于 2021-8-21 19:59
https://www.aliyundrive.com/s/ifzfsgrHHQn 加油,又兴趣分析下这个吗?
stevejobs111 发表于 2021-8-21 21:23
持之以恒,才能无懈可击
咔c君 发表于 2021-8-21 22:38
学习了不错
从那以后的你 发表于 2021-8-22 00:04
谢谢分享
tohyueyun 发表于 2021-8-22 00:09
佩服楼主的坚持。给您点赞
aidjgo 发表于 2021-8-22 00:11
待道友渡劫成功时,再考虑修不修真
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-16 03:48

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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