下载附件,用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}