BUUCTF逆向wp [HDCTF2019]Maze

第一步  查壳,本题是32位,有壳,进行脱壳。

第二步    这里的 jnz 指令会实现一个跳转,并且下面的0EC85D78Bh被标红了,应该是一个不存在的地址,这些东西就会导致IDA无法正常反汇编出原始代码,也称为花指令。(如下图)

我们把先把jnz指令右键nop,之后再将call指令变成数据再进行下一步nop。

点击call指令,按D数据化后尝试先把第一个数据nop掉,之后尝试建立主函数,如果不行的话再将下一个数据也nop掉。

nop完后从这里开始到00401128,按p构建main函数。

构建后是这个样子,我们跟进main

这里有关本题解决花指令的方法详情前参考这篇文章:

[HDCTF2019]Maze(考点:去花)_[hdctf2019]maze 题解-CSDN博客

第三步   按tab键转换(红色的不用管,可能是我脏字节没弄干净,不影响)。

分析一下这段代码:

其中终点为(5,-4),因此后面显示congratulations的字样。

函数调用和输入读取

  1. sub_401140(aGoThroughTheMa);
    • 调用函数 sub_401140 并传入参数 aGoThroughTheMa,这可能是一个提示或指示信息。
  2. v5 = scanf("%14s", v7);
    • 使用 scanf 从标准输入读取最多14个字符的字符串到变量 v7 中,并将读取的字符数赋值给 v5。

循环处理用户输入

  1. for (i = 0; i <= 13; ++i)
    • 遍历用户输入的每个字符(最多14个),进行相应的处理。
  2. switch (v7[i])  根据当前字符 v7[i] 的值,执行不同的操作:
    • default: continue;
      • 对于其他字符,继续下一次循环。
    • case 'w': ++dword_40807C;
      • 如果字符是 'w',则增加变量 dword_40807C 的值。
    • case 's': --dword_40807C;
      • 如果字符是 's',则减少变量 dword_40807C 的值。
    • case 'd': ++*(_DWORD *)asc_408078;
      • 如果字符是 'd',则增加 asc_408078 指向的 DWORD 类型的值。
    • case 'a': --*(_DWORD *)asc_408078;
      • 如果字符是 'a',则减少 asc_408078 指向的 DWORD 类型的值。

结果判断

  1. if (*(_DWORD *)asc_408078 == 5 && dword_40807C == -4)
    • 检查 asc_408078 指向的值是否为5,并且 dword_40807C 的值是否为-4。这两个条件可能代表了玩家需要达到的目标状态。
  2. 成功与否的处理
    • 成功 (true 分支)
      • sub_401140(aCongratulation);
        • 调用 sub_401140 并传入 aCongratulation,可能用于显示恭喜信息。
      • sub_401140(aHereIsTheFlagF);
        • 调用 sub_401140 并传入 aHereIsTheFlagF,可能用于显示成功获得的奖励或标志。
    • 失败 (else 分支)
      • sub_401140(aTryAgain);
        • 调用 sub_401140 并传入 aTryAgain,提示用户再次尝试。

返回值

  1. return 0;
    • 函数返回0,通常表示程序执行成功。

我们在代码中发现“a”“s”“d”“w”四个操作对应我们键盘上的四个按键,这是迷宫问题的典型特征。

跟进一下asc_408078(或dword_40807C),得到如下信息:

a和d控制左右,w和s控制上下,因此asc对应横着的第几列,dword对应竖着的第几行

上图告诉我们,起点为(7,0)。

我们推测:+对应的是起点,F对应的是终点(之前的迷宫题目也是差不多的)

第四步   编写脚本

分析一下脚本:

  1. 变量定义和查找
    • maze 是一个包含迷宫字符的字符串。
    • sid 和 eid 分别是字符 '+' 和 'F' 在 maze 中的索引位置。
  2. 计算行和列
    • ex, ey 被定义为 -4 和 5。这些值在代码中的具体含义不明确,但看起来像是尝试定义某种“步长”或“方向”。
    • c = (eid - ey) // (-ex) 计算列数。这里的计算方式比较特殊,看起来是尝试根据某种规则来确定列宽。
    • r = len(maze) // c 计算行数,即迷宫的总长度除以每行的字符数。
  3. 输出迷宫
    • 循环从 0 到 r,每次循环打印从 c*i 到 c*(i+1) 的子字符串,这应该是尝试将一维字符串按照每行 c 个字符分割成多行。

r = 7 (即7行)

c = 10(即10列)

为了方便读者理解F的位置ex,ey =(5,-4)我在下面的图上标出了坐标轴,类似于把该迷宫放在第四象限。

flag{ssaaasaassdddw}

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

无 双

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值