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

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

丢进IDA,F5看伪代码

看到main中的关键代码
- scanf("%20s", s); //最多不读入20个字符
- v5 = strlen(s);
- if ( v5 == 14 && (*(unsigned int (__fastcall **)(char *))judge)(s) )
- puts("Right!");
输入字符的长度需要是14,并且要和judge不知道什么鬼操作
且judge还是已函数调用的形式使用的。judge为数据,作为函数使用,有点神奇
(*(unsigned int (__fastcall **)(char *))judge)
fastcall 一个char*,返回int。
找到judge数据位置

这里judge 已经放了一些初始数据,然后这些数据会经过^0xc后再被使用
- for ( i = 0; i <= 181; ++i )
- 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值
最终代码
- from ida_bytes import *
- addr=0x600b00
- for i in range(182):
- patch_byte(addr+i,get_byte(addr+i)^0xC)
运行,然后可以看到此时的judge的值已经被我们的脚本修改完了

还是这个位置
重新生成汇编代码看看(按c)
之后就可以看到judge这玩意被重新处理成了代码

光标还是在public judg的位置
重新生成函数(按p)
然后你就可以按f5看到judge的反汇编代码了

唉,到这步就简单了。首先
- v2 = "fmcd" + 0x7F
- v3 = "k7d;V`;np"
先对我们的输入a1每一位进行本身亦或i
- for ( i = 0; i <= 13; ++i )
- *(_BYTE *)(i + a1) ^= i;
再对处理之后的每一位if校验,不等于v2[i]则return 0
- for ( i = 0; i <= 13; ++i )
- {
- if ( *(_BYTE *)(i + a1) != v2[i] )
- return 0LL;
- }
- return 1LL;
不过这个v2看起来好像有点问题,,v2最大才5位长度,而这里有14轮循环,恰巧v2+v3是14的长度。。。小小猜测一下,其实应该是亦或之后要等于v2+v3。
已知亦或完了之后要等于"fmcd" +0x7F+"k7d;V`;np",很容易推出原字符串
代码
- input = "fmcd" + chr(0x7f) + "k7d;V`;np"
- res = ''
- for i, c in enumerate(input):
- res += chr(ord(c) ^ i)
- print(res)
-
- """output
- flag{n1c3_j0b}
- """

flag{n1c3_j0b}