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

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 13554|回复: 58
收起左侧

[CTF] 广西CTF省赛之labyrinth

  [复制链接]
姚小宝 发表于 2018-11-9 17:59
本帖最后由 yechen123 于 2018-11-10 13:24 编辑

这应该是在比赛中分值最高的一道逆向题了


先上传题目
labyrinth.rar (31.14 KB, 下载次数: 65)

链接: https://pan.baidu.com/s/1dMbescIDsS8x9UPVhXfijA 提取码: x47w


当时是在比赛中下午看的题目 脑子很乱 英语也不好 看到labyrinth第一个反应是出生或者出生日期
然后整个思路就乱了  在回来之后也简单看了下 发现还是很乱就放弃了 果然还是自己太菜了

昨晚无聊查了下labyrinth发现时迷宫的意思  就想着今天下午再解一下

当知道是迷宫的意思后再看代码有种豁然开朗的感觉
果然逆向一开始还是要把握一个整体啊

写个文章记录一下自己学习的过程  可能会有错误 希望各位师傅不要嫌弃


开始

查壳 无壳


IDA打开
[Asm] 纯文本查看 复制代码
int __cdecl main_0(int argc, const char **argv)
{
  if ( argc == 2 )
  {
    memset(byte_42AE58, -1, 0x1E4u);
    sub_40100A();
    sub_40100F();
    if ( sub_401019((char *)argv[1]) )          // 输入参数
    {
      sub_401005((int)argv[1]);
      return 0;
    }
    printf("You get lost!");
  }
  return 0;
}

发现是命令行下带参数输入  不然会自动关闭软件


[Asm] 纯文本查看 复制代码
memset(byte_42AE58, -1, 0x1E4u);
sub_40100A();
sub_40100F();

这三个主要是生成一个迷宫

主要代码在sub_401019((char *)argv[1])中

再看看sub_401005((int)argv[1]);
[Asm] 纯文本查看 复制代码
int __cdecl sub_401650(int a1)
{
  char v2[48]; // [esp+4Ch] [ebp-38h]
  char v3; // [esp+7Ch] [ebp-8h]
  int i; // [esp+80h] [ebp-4h]

  for ( i = 0; i < 48; ++i )
    v2[i] = byte_427A98[i] ^ *(_BYTE *)(a1 + i % 16);// 16个字节
  v3 = 0;
  return printf("%s\n", v2);
}

主要是根据输入的值与内存的值异或输出flag
(a1 + i % 16)这里可以猜测输入是16位的字符

最后看最主要的代码sub_401019((char *)argv[1])
[Asm] 纯文本查看 复制代码
BOOL __cdecl sub_4013A0(char *input)
{
  char *input_strpy; // [esp+50h] [ebp-30h]
  int lie; // [esp+58h] [ebp-28h]
  signed int v4; // [esp+5Ch] [ebp-24h]
  int input_two_ascii; // [esp+60h] [ebp-20h]
  int v6; // [esp+64h] [ebp-1Ch]
  int local.6; // [esp+68h] [ebp-18h]
  signed int v8; // [esp+6Ch] [ebp-14h]
  int hang; // [esp+70h] [ebp-10h]
  signed int input_one_ascii; // [esp+74h] [ebp-Ch]
  int v11; // [esp+78h] [ebp-8h]
  int local.1; // [esp+7Ch] [ebp-4h]

  input_strpy = input;
  if ( strlen(input) & 1 )                      // 必须为偶数
    return 0;
  input_one_ascii = *input;                     // 第一个字符
  local.1 = 0;                                 
  v11 = 0;
  hang = 0;
  v8 = -1;
  local.6 = 0;
  if ( !*input )
    goto LABEL_22;
  v6 = 0;
  do
  {
    if ( input_one_ascii < 97 || input_one_ascii > 100 )// 如果不是abcd
      goto LABEL_10;
    input_two_ascii = input_strpy[1] - 101;
    if ( input_two_ascii > 21 )                 // 
    {
      input_strpy = input;
LABEL_10:
      ++local.1;
      goto LABEL_19;
    }
    v4 = v8;
    switch ( input_one_ascii )
    {
      case 97:
        v8 = 0;
        hang = (hang - input_two_ascii) % 22;
        v6 = byte_42AE58[22 * v11 + hang];      
        break;
      case 98:
        v8 = 0;
        hang = (hang + input_two_ascii) % 22;
        goto LABEL_17;
      case 99:
        lie = v11 - input_two_ascii;
        goto LABEL_16;
      case 100:
        lie = v11 + input_two_ascii;            // 2
LABEL_16:
        v8 = 1;
        v11 = lie % 22;
LABEL_17:
        v6 = byte_42AE58[22 * v11 + hang];      // 9
        break;
      default:
        break;
    }
    byte_42AE58[22 * v11 + hang] = 0;
    local.1 = (v4 == v8) + (v6 ^ 1) + local.6;
    input_strpy = input;
LABEL_19:
    input_one_ascii = input_strpy[2];           
    input_strpy += 2;                         
    local.6 = local.1;
    input = input_strpy;
  }
  while ( input_one_ascii );
  if ( v11 != 21 || hang != 21 ) 
LABEL_22:
    ++local.1;
  return local.1 <= 0;
}


首先这个函数的最下面的是return local.1 <= 0;
如果想返回一个1 那么local.1必须小于等于0

再看看让local.1值变动的语句
LABEL_22:
    ++local.1;

LABEL_10:
      ++local.1;

local.1 = (v4 == v8) + (v6 ^ 1) + local.6;
local.6 = local.1;
这就代表不能执行label 22 和 10

也就是输入的字符在偶数位的字符串不能大于z

2.png

还有  这个条件不能成立
3.png

还有
local.1 = (v4==v8) + (v6^1) + local.6;
local.6 = local.1;
每次循环v4不能等于v8  v6必须为1


达到这样的条件 才能得到flag


好了 现在说主要代码
走迷宫的话 得控制方向吧  可能是awds 或者是abcd  这里是abcd
[Asm] 纯文本查看 复制代码
    v4 = v8;
    switch ( input_one_ascii )
    {
      case 97:
        v8 = 0;
        hang = (hang - input_two_ascii) % 22;
        v6 = byte_42AE58[22 * v11 + hang];      // 里面都是1
        break;
      case 98:
        v8 = 0;
        hang = (hang + input_two_ascii) % 22;
        goto LABEL_17;
      case 99:
        lie = v11 - input_two_ascii;
        goto LABEL_16;
      case 100:
        lie = v11 + input_two_ascii;            // 2
LABEL_16:
        v8 = 1;
        v11 = lie % 22;
LABEL_17:
        v6 = byte_42AE58[22 * v11 + hang];      // 9
        break;
      default:
        break;
    }

这个思路是 每次从输入字符串中取两个字符  

input_one_ascii为第一个  必须为abcd  控制方向
input_two_ascii为第二个 控制往该方向行走的路程
从代码看出 a是往左边 b是右边 c是上边 d是下边
还可以发现不管是上下左右  都有%22的代码 所以这是一个22*22的迷宫
还发现有v8=1 或者v8=0的代码 刚刚说了 v4!=v8  所以左右或者上下不能重复
比如说这次往左边走了  下次就只能往上下走了 以此类推
解析结束

看一下迷宫
4.png
每一次走到的位置必须是01 还有最后一步必须到达右下角的01  也就是迷宫的出口 迷宫的入口在最左上角的地方


其实这个迷宫有些值是随机的 但是如果能解题 有一些值肯定是固定的!
写个脚本把每次生成的迷宫对比一下
[Asm] 纯文本查看 复制代码
f = open('1.txt', 'r')
g = open('2.txt', 'r')
one = []
ones = ''

two = []
twos = ''

ones = f.readline()
twos = g.readline()
count = 0
while count<22:
  ones = ones.split(' ')
  twos = twos.split(' ')

  for i in range(22):
      if ones[i] == twos[i] and ones[i]!='00' and ones[i]!='00\n':
          #print ones[i]
          print str(count)+':'+str(i)

  ones = f.readline()
  twos = g.readline()
  count += 1


5.png
标红的地方 就是固定的01的值

可以推测步数
6.png
ok  得到key为dpbucmandtbidhbo
7.png
解题结束

后记
其实从后边的输出函数逆推可能会得到flag
上次以为开头的是flag{格式的 尝试逆推  推出Congratulations!  you_are_a 等字符 后来感觉有点乱放弃了  有兴趣的师傅可以尝试一下


免费评分

参与人数 13吾爱币 +13 热心值 +11 收起 理由
lchhhhhh + 1 + 1 我很赞同!
潇洒超人 + 1 牛批
stunyeah + 1 + 1 用心讨论,共获提升!
金野喵君 + 1 谢谢@Thanks!
你的燚龘 + 1 + 1 我很赞同!
zhengjim + 1 + 1 谢谢@Thanks!
false1 + 1 + 1 热心回复!
这里是废物 + 1 谢谢@Thanks!
youhen233 + 1 + 1 谢谢@Thanks!
敛弈逆袭 + 3 + 1 我很赞同!
大将军 + 1 用心讨论,共获提升!
拿破仑骑乌龟 + 1 + 1 谢谢@Thanks!
lihaohua + 1 + 1 我很赞同!

查看全部评分

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

jimo 发表于 2018-11-9 18:08
随机迷宫 有点强!
lihaohua 发表于 2018-11-9 18:21
wangqiustc 发表于 2018-11-9 18:24
 楼主| 姚小宝 发表于 2018-11-9 18:55

师傅比较厉害
小宾是老子 发表于 2018-11-9 19:43
表示从头看不懂,大神给点入门的方法。比如要买啥书之类的?
回归自然 发表于 2018-11-9 21:07

给楼主点赞
yssun 发表于 2018-11-9 22:05
师傅比较厉害
单程线 发表于 2018-11-9 23:48 来自手机
请收下我的膝盖
hshtzlove 发表于 2018-11-9 23:56
有点意思啊
您需要登录后才可以回帖 登录 | 注册[Register]

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

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

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

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

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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