吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 8997|回复: 38
收起左侧

[CTF] 学破解第78天,《攻防世界reverse新手练习区game分析》

  [复制链接]
小菜鸟一枚 发表于 2020-1-4 15:58
本帖最后由 小菜鸟一枚 于 2020-1-4 16:02 编辑

学破解第78天,《攻防世界reverse新手练习区game分析》

前言:
一直对黑客充满了好奇,觉得黑客神秘,强大,无所不能,来论坛两年多了,天天看各位大佬发帖,自己只能做一个伸手党。也看了官方的入门视频教程,奈何自己基础太差,看不懂。自我反思之下,决定从今天(2019年6月17日)开始定下心来,从简单的基础教程开始学习,希望能从照抄照搬,到能独立分析,能独立破解。
不知不觉学习了好几个月,发现自己离了教程什么都不会,不懂算法,不懂编程,随着破解学习的深入,越发的觉得自己没有基础,所以从第71天起,开始接触一门编程语言C++,开启新的学习之路。


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

为啥选择它呢?当然是因为楼主是个小菜鸟,这道题简单,就拿它分析分析了!

1.下载程序

这是一个exe文件,那我就放心,至少可以在window上执行,可以用OD。
1.png

2.观察程序

直接将程序运行起来,一堆英文,看不懂,右键复制,丢到有道翻译里面去。
2.png
有道翻译如下:
玩一个游戏
n是灯的序列号,m是灯的状态
如果第n盏灯的m是1,它是亮的,如果不是,它是灭的
起初所有的灯都是关着的
现在你可以输入n来改变它的状态
但是你要注意一件事,如果你改变第N盏灯的状态,第(N-1)个和第(N+1)个的状态也会改变
当所有的灯都亮着时,旗子就会出现
现在,输入n
输入n, n (1 - 8)

游戏规则清楚了,但是我显然智商没那么高,玩不来,那就只能老老实实对它使用吾爱的神器OD了。前灯亮,相邻的两个灯同时改变自身状态。

思考:我们能不能点一个亮一个,不改变相邻灯的状态呢?

3.使用OD调试

首先查壳,Microsoft Visual C++ ver.14 [Deb] / Visual Studio 2015 [ Debug:02 ] ,ep区段.text   应该是无壳的C++程序!

  然后将程序丢进OD,停在了01417839 这里,直接右键搜索中文字符串,搜到了一大堆提示信息,我找到程序提示的游戏规则的最后一句input n,n(1-8),找到这一行回车进去,来到了:

0141F508  |.  68 7CB54C01   |push 9c91e9fd.014CB57C                  ;  input n,n(1-8)\n
0141F50D  |.  E8 ACB2FFFF   |call 9c91e9fd.0141A7BE
0141F512  |.  83C4 04       |add esp,0x4
0141F515  |.  E8 FE9EFFFF   |call 9c91e9fd.01419418
0141F51A  |.  68 90B54C01   |push 9c91e9fd.014CB590                  ;  n=

  一路F8单步往下跟,在0131F530 这一个call程序跑起来等待我们输入n,输入完之后继续单步向下走,然后就看到了CLS清屏命令,随后灯的状态就改变了。

暂时失去了思路
  再去看看字符串有没有哪些可用的信息,我看到了这个字符串:done!!! the flag is ,大意就是说成功了,flag是
但是我们没有看到这句话出来,我猜测是不是把这句话显示出来就能看到flag呢?

  我回车进去,定位到了这一段代码:

013EE940  /> \55            push ebp
013EE941  |.  8BEC          mov ebp,esp
013EE943  |.  81EC 58010000 sub esp,0x158
013EE949  |.  53            push ebx
013EE94A  |.  56            push esi
013EE94B  |.  57            push edi
013EE94C  |.  8DBD A8FEFFFF lea edi,[local.86]
013EE952  |.  B9 56000000   mov ecx,0x56
013EE957  |.  B8 CCCCCCCC   mov eax,0xCCCCCCCC
013EE95C  |.  F3:AB         rep stos dword ptr es:[edi]
013EE95E  |.  A1 04204C01   mov eax,dword ptr ds:[0x14C2004]         ;  蛾Am
013EE963  |.  33C5          xor eax,ebp
013EE965  |.  8945 FC       mov [local.1],eax
013EE968  |.  68 F0B04901   push 9c91e9fd.0149B0F0                   ;  done!!! the flag is
013EE96D  |.  E8 4CBEFFFF   call 9c91e9fd.013EA7BE

我们现在就要一步一步向上回溯,找到跳转到这里的位置
点击段首,看信息窗口,CTRL+G向上找,依次找到:013EE940《-013E7AB4 《-013EF66C
我们向上翻翻,看到了CLS,我现在又有一个思路了:能不能在清屏后重新显示菜单的的时候让它调用这个call直接显示flag呢?
那我就F4到CLS这里,n随便输入一个5

013EF5B7  |> \68 BCB54901   |push 9c91e9fd.0149B5BC                  ;  CLS
013EF5BC  |.  E8 F68BFFFF   |call 9c91e9fd.013E81B7
013EF5C1  |.  83C4 04       |add esp,0x4
013EF5C4  |.  E8 8B8AFFFF   |call 9c91e9fd.013E8054
013EF5C9  |.  B8 01000000   |mov eax,0x1

  看这里,第一个call就是调用系统的清屏命令,第二个call回车进去看了下,就是打印菜单,那就说明灯的状态在CLS之前就已经改变了,看来前面是我错过那个了CALL,继续看,后面紧接着就是013EF66C这个call,肯定是被跳转过去了,继续单步,来到这里,看图,这个jnz不能让它跳!
3.png
然后后面代码和这一块类似,很容易猜测到是判断其它7个灯是不是亮的,我就不用去一个一个nop了,直接将第一个jnz改成jmp。
0023F5DB     /E9 8C000000   jmp 9c91e9fd.0023F66C
复制到可执行文件,保存为1.exe,运行程序后,随便输入一个数字即可得到正确的falg,如图所示!
33.png
到这里,我们就成功的使用OD找到了flag!

4.使用IDA进行分析

将程序丢进IDA,在左侧的函数栏CTRL+F搜索main函数,F5反汇编一下,看到

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax

  main_0();
  return result;
}

  我们往下跟,看到它调用了main_0函数,点进去,来到了如图所示的地方!
4.png
前面都是些打印提示语函数,直接略过,看下面这段反汇编代码,我给它加了注释

while ( 1 )//死循环,让游戏不会结束
  {
    while ( 1 )
    {
      sub_45A7BE("input n,n(1-8)\n");
      sub_459418();\\1.△ 2.○ 3.◇ 4.□ 5.☆ 6.▽ 7.( ̄▽ ̄)/ 8.(;°Д°) 0.restart
      sub_45A7BE("n=");
      sub_4596D4("%d", &v1);\\接收输入的数字
      sub_45A7BE("\n");
      if ( v1 >= 0 && v1 <= 8 )//判断输入的值是否在1-8的范围内,否则重新开始游戏
        break;
      sub_45A7BE("sorry,n error,try again\n");
    }
    if ( v1 )//v1也不能等于0
    {
      sub_4576D6(v1 - 1);//
    }
    else//否则将所有灯关掉,m全部设为0
    {
      for ( i = 0; i < 8; ++i )
      {
        if ( (unsigned int)i >= 9 )
          j____report_rangecheckfailure();
        byte_532E28[i] = 0;
      }
    }
    j__system("CLS");
    sub_458054();//改变灯的状态
    if ( byte_532E28[0] == 1
      && byte_532E28[1] == 1
      && byte_532E28[2] == 1
      && byte_532E28[3] == 1
      && byte_532E28[4] == 1
      && byte_532E28[5] == 1
      && byte_532E28[6] == 1
      && byte_532E28[7] == 1 )
    {
      sub_457AB4();//如果灯全部亮,输出flag
    }
  }

加上注释后,是不是一目了然呢,我们看到上面的代码瞬间涌现出两种思路:
1.输入一个0,在OD中找到'00FDF59D      C681 282E0B01>mov byte ptr ds:[ecx+0x10B2E28],0x0'这一行,然后改为0x1,我们保存出去,输入0,即可得到flag。
2.跟进sub_457AB4();这个函数,看flag是怎么算出来的。

5.flag算法还原与总结

前面已经通过IDA和OD分别获取到了flag,我们进去看一下sub_457AB4()函数的代码,如何运算出我们的flag的,F5反编译一下
核心算法在这:

 for ( i = 0; i < 56; ++i )
  {
    *(&v2 + i) ^= *(&v59 + i);
    *(&v2 + i) ^= 0x13u;
  }

  前面都是定义的一堆变量v59-v115为一段,v2-v58为一段,看for循环(&v2 + i) ^= (&v59 + i);,可以看做a[i]^b[i],然后a[i]^0x13u得到解密后的字符。

整理一下,最终改写成C语言代码如下:

int sub_45E940()
{
        int i; 

        int arr1[]={18,64,98,5,2,4,6,3,6,48,49,65,32,12,48,65,31,78,62,32,49,32,1,57,96,3,21,9,4,62,3,5,4,1,2,3,44,65,78,32,16,97,54,16,44,52,32,64,89,45,32,65,15,34,18,16,0};
        int arr2[]={123,32,18,98,119,108,65,41,124,80,125,38,124,111,74,49,83,108,94,108,84,6,96,83,44,121,104,110,32,95,117,101,99,123,127,119,96,48,107,71,92,29,81,107,90,85,64,12,43,76,86,13,114,1,117,126,0};

        for(i = 0;i < 56; i++)
        {
                arr1[i] ^= arr2[i];
                arr1[i] ^= 0x13u;
                printf("%c",arr1[i]);
        }
        return 1;
}

int main(int argc, char* argv[])
{
        printf("Hello World!\n");
        sub_45E940();
        getchar();
        return 0;
}

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

PS:IDA不会用,这一部分的分析参考了其他大佬的分析!

免费评分

参与人数 19吾爱币 +19 热心值 +17 收起 理由
XXX_Echoed + 1 + 1 我很赞同!
夏晓健 + 1 + 1 加油哦
拖地僧 + 1 热心回复!
玖公子 + 1 + 1 用心讨论,共获提升!
ZIfumaker + 1 用心讨论,共获提升!
jinxiaoyun + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
小僧 + 1 用心讨论,共获提升!
夏南离 + 1 + 1 用心讨论,共获提升!
tte + 1 + 1 用心讨论,共获提升!
ysgbaby + 1 我很赞同!
KSTG_茶飘香 + 1 + 1 热心回复!
bdzbai + 1 用心讨论,共获提升!
asdf45710 + 1 + 1 我很赞同!
smile5 + 1 热心回复!
Dkkk24 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
小糊涂虫 + 5 + 1 还在坚持啊,加个分
我有一只苍阿姨 + 2 + 1 我很赞同!
coralzyzy + 1 + 1 用心讨论,共获提升!
朱朱你堕落了 + 1 + 1 进步如何神速,看来天赋很重要。

查看全部评分

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

storm 发表于 2020-1-4 20:06
楼主学的哪套教程 能学这么长时间
 楼主| 小菜鸟一枚 发表于 2020-1-4 20:10
本帖最后由 小菜鸟一枚 于 2020-1-4 22:05 编辑
storm 发表于 2020-1-4 20:06
楼主学的哪套教程 能学这么长时间

当然是论坛的零基础入门教程呀,这是我全部的学习记录https://www.52pojie.cn/thread-1067012-1-1.html,你也可以参考下
头像被屏蔽
D.c 发表于 2020-1-4 16:15
dhz0105 发表于 2020-1-4 16:39
能学了78天,牛逼!我是没耐心看教程,收藏从未停止。
xiaoxiaoshitou 发表于 2020-1-4 16:52
都是大神啊,看都看不懂,佩服
俺是大绅士 发表于 2020-1-4 17:16
感谢分享,来看看
速度富贵浮云 发表于 2020-1-4 17:20
已经很不错了
头像被屏蔽
夏南离 发表于 2020-1-4 17:30
提示: 作者被禁止或删除 内容自动屏蔽
30900 发表于 2020-1-4 17:48
路过,真的是精彩绝伦,感谢大神分享,学习了!
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-16 15:55

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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