• [攻防世界 XCTF 4th-WHCTF-2017] BABYRE


     下载附件,用Exeinfo看一下信息先

     64位Linux程序,跑一下先看看

    丢进IDA,F5看伪代码

     看到main中的关键代码

    1. scanf("%20s", s); //最多不读入20个字符
    2. v5 = strlen(s);
    3. if ( v5 == 14 && (*(unsigned int (__fastcall **)(char *))judge)(s) )
    4. puts("Right!");

     输入字符的长度需要是14,并且要和judge不知道什么鬼操作

    且judge还是已函数调用的形式使用的。judge为数据,作为函数使用,有点神奇

    (*(unsigned int (__fastcall **)(char *))judge)

    fastcall 一个char*,返回int。 

    找到judge数据位置

     这里judge 已经放了一些初始数据,然后这些数据会经过^0xc后再被使用

    1. for ( i = 0; i <= 181; ++i )
    2. judge[i] ^= 0xCu;

    我们在ida中再走一遍亦或流程,把ida中的数据改为亦或后的数据,才能在ida中做进一步分析处理。

    众所周知,在ida中我们可以修补程序, 对汇编代码和数据段都可以随意改动。

     比如修改某个地址的byte数据可以如上操作,不过,,手动一个个点开改还是太麻烦了

    所以我们可以在IDA中使用脚本语言处理

     

    然后写上代码run就好了。 

    不过由于网上的脚本版本都有些久远,可能已经不再兼容ida7.5以上版本,可能会报一些NameError: name Byte is not defined,之类的错误,我们想写用新一点ida写使用脚本方法咋办呢。

    这告诉我们学习照抄是不行的,要自己掌握解决问题的思路和方法。

     看这里,点开Help,API文档,选择你想看的API,我对py比较熟,就写py好了。点开py文档

    (如果你恰巧线下比赛没网,也可以参考ida主目录下的idahelp.chm文件)

     由于我们是要对byte进行操作,点开ida_bytes模块看看。

    点开后,看到get_byte函数,

    作用就是 Get the specified number of bytes of the program

    传入地址,返回一个byte

    再看到patch_byte函数,

    看作用,就是我们要干的 Patch a byte of the program.

    传入一个地址,一个uint64,返回bool值

     最终代码

    1. from ida_bytes import *
    2. addr=0x600b00
    3. for i in range(182):
    4. patch_byte(addr+i,get_byte(addr+i)^0xC)

    运行,然后可以看到此时的judge的值已经被我们的脚本修改完了

    还是这个位置

    重新生成汇编代码看看(按c)

    之后就可以看到judge这玩意被重新处理成了代码

     光标还是在public judg的位置

    重新生成函数(按p)

    然后你就可以按f5看到judge的反汇编代码了

     唉,到这步就简单了。首先

    1. v2 = "fmcd" + 0x7F
    2. v3 = "k7d;V`;np"

    先对我们的输入a1每一位进行本身亦或i

    1. for ( i = 0; i <= 13; ++i )
    2. *(_BYTE *)(i + a1) ^= i;

    再对处理之后的每一位if校验,不等于v2[i]则return 0

    1. for ( i = 0; i <= 13; ++i )
    2. {
    3. if ( *(_BYTE *)(i + a1) != v2[i] )
    4. return 0LL;
    5. }
    6. return 1LL;

    不过这个v2看起来好像有点问题,,v2最大才5位长度,而这里有14轮循环,恰巧v2+v3是14的长度。。。小小猜测一下,其实应该是亦或之后要等于v2+v3。

    已知亦或完了之后要等于"fmcd" +0x7F+"k7d;V`;np",很容易推出原字符串

    代码

    1. input = "fmcd" + chr(0x7f) + "k7d;V`;np"
    2. res = ''
    3. for i, c in enumerate(input):
    4. res += chr(ord(c) ^ i)
    5. print(res)
    6. """output
    7. flag{n1c3_j0b}
    8. """

    flag{n1c3_j0b}

  • 相关阅读:
    vscode访问远程服务器的图形界面如firefox
    阿里云等企业主导的龙蜥社区发起“龙腾计划”;OpenInfra 基金会推出 LOKI 标准;GitLab 14.6 发布 | 开源日报
    5256C 5G终端综合测试仪
    pyinstaller打包技巧
    如何借助自动化工具落地DevOps|含低代码与DevOps应用实践
    【luogu CF633H】Fibonacci-ish II(莫队)(线段树)(矩阵乘法)
    工程伦理--13.4 临平净水厂化解“邻避效应”的对策
    C访问数据对象在内存中的位模式
    nginx系列第一篇:nginx源码下载,编译和安装
    理解ASP.NET Core - 全球化&本地化&多语言(Globalization and Localization)
  • 原文地址:https://blog.csdn.net/czw2479/article/details/126034989