

die查看发现是elf文件,且为64位程序
于是改一个后缀名再用ida64打开

看到主函数,发现输入长度为32位,这个长度好像一般都是那种MD5之类的长度,然后这个mprotect是关于给这个文件权限之类的,这里不重要,随即就是一个for循环,这个是将这个sub_402219进行异或操作,这个一开始我还真的挺蒙的,也不知道是个什么操作,于是就看了一些题解
这里相当于直接就去改这个程序了,所以我们照着这个操作去做,先找到这个东西的地址
点进去,然后按tab键

随即就到了这个位置

这里这么多字节序肯定是有问题的,这里我们直接选中这个sub_402219,然后按D就可以将其转位data数据

是这个样子的,然后再选中这些数据按D就可以将这些转为数据

这里我们要将数据修改可以通过ida内置的idc,我们通过shift+F2调出窗口,这个idc的语法和C差不多,也是用分号表示结束,然后声明变量用auto
\#include <idc.idc>
static main()
{
auto addr=0x402219;
auto i;
for(i=0;i<224;i++){
PatchByte(addr+i,Byte(addr+i)^153);
}
}
然后用上面的代码运行一下,这里地址就是那个数据的起始位置,然后运行224次,这个PatchByte的用法就是将某一个地址值改为后面的那个结果,后面的Byte应该就是去那个地址的数值,然后与153进行异或运算就可以完成上诉要求
运行完结果是这样的

然后我们再选中这个函数的所有数据,然后右键,点击这个Ana...的东西,然后选择force



于是这个就变成未声明的形式了,于是我们点击这个函数头再按一下P,就会神奇的发现,这个变成一个函数了
然后再次点击就会发现可以查看了

于是我们再去查看一下这个sub_401CF9函数

发现这个好像是MD5的特征值,说明这个结果就是将输入进行MD5处理,那么这个a1的结果就是前面这里结果Md5再拼接再MD5之后的结果,这个看起来是v2进行MD5,但是实际上这个v2,v3...他们是一个数组的
但是我试了一下,发现直接求还是有点太麻烦了,所有可能需要换个方法,但是我们接着看后面的代码

这个代码的第一个函数中的unk_603170好像就是前面的a1,那么这个到底是在干啥再点进去看看


这个63,7C,77,7B好像是AES黑盒操作的特征值,那么这个函数应该就是AES了,第一个函数就是将这个结果作为初始密钥,然后将明文分组,分别与密钥进行异或操作
那么后面那两个40196E,第一个对前16位进行处理,第二个对后16位进行处理,然后结果再与一个数组进行比较判断

这里我们选中数据,然后shift+e就可以将数据提取出来,这里提取为32位16进制。那么这里我们就得到结果了,那么我们只需要再得到密钥就可以将明文得到啦

由于是elf文件,所有ida本地调试不了,这里我们直接用linus系统的gdb或者选择远程linus动态调试去得到前面的那个结果,这里我也是第一次远程调试,然后也在网上看了一些题解,发现他们都是好不容易得到那个结果,但是过程并不是很详细,这里我就主要详细描述一下这个动态的过程
首先找到ida dbgsrv下面的这两个文件


然后我们修改文件权限,以便能够运行
这里远程动态调试需要几个参数


前面两个就是这个文件的位置,一般不用修改,然后中间那个Parameters可以不要填,主要是填写远程虚拟机的ip地址和端口号,以便可以连接。
这里还有一个需要注意的一点是主机的防火墙最好关一下,以便可以正常连接
所以这里我们先查看远程虚拟机的ip地址
虚拟机查看ip的命令是ifconfig

然后我们找到这个inet addr 然后复制这个地址到本地ida,然后再运行对应的linus_server,这个程序是64位的,所以我们运行那个后面有64的
输入命令./linux_server64

就启动成功了
然后再配置本地的ida

这样就差不多可以了
OK之后就会到这样的界面

然后虚拟机里面输入长为32的字符串就可以动态调试了,由于这里我们没有设置断点,所以输入完之后就会显示一个wrong
那么现在就是要去设置断点了

我们先找到这个参数的位置,然后点击tab键

然后就到了这个位置,于是我们再点击空格,就可以到汇编语言的位置

这个好像是一个判断,那么我们断点就是选中设置在这个判断的地方,然后再在这个数据的地方设置一个断点,然后差不多就可以运行程序了,像下面这样的

这里输入完之后就到了这个位置了

然后我们点击空格,查看汇编代码

会发现,这个程序左边的箭头一直闪烁,说明程序会往左边跳转,可是我们要让他往右边跳啊,那么该怎么办呢,这里我们也不要对这个程序进行太多的操作,只是看一下那个数组的结果,所以就不去分析内在逻辑了,直接用keypatch这个插件,这个插件需要去下载,这里就不过多说明了,然后我们在判断的地方加一个n,像这样.于是将jle改为了jg,这样就可以去另一个方向跳转了

这里改完之后前停止,然后重新运行一下
如果直接运行的话就会有问题,因为已经是修改的程序了,所以运行逻辑就会有问题

改完之后是这个样子的,然后我又发现了,改完之后重新运行又改回去了,原因就是这个程序本身逻辑是这样的,所以这里解决办法就是在输入之前进行修改,然后再输入

改好之后运行到这个代码之后就会发现这个地址有数据了,而且这个数据就是我们需要的key!!!
然后我们再点击这个地址,选中数据

再shift+e就可以提取这些数据,这里也是用16进制提取

之后我们就可以去写解密脚本啦,由于我也是第一次做这种AES的题目,所以也是看着大佬的wp才略懂一些的
from Crypto.Cipher import AES
from Crypto.Util.number import *
k1=0xCB8D493521B47A4CC1AE7E62229266CE
m1=0xbc0aadc0147c5ecce0b140bc9c51d52b46b2b9434de5324bad7fb4b39cdb4b5b
key = long_to_bytes(k1) # 密钥
mi = long_to_bytes(m1) # 密文
# print(mi)
lun = AES.new(key, mode=AES.MODE_ECB) #ECB模式是有一个密钥,然后将明文分组加密
flag = lun.decrypt(mi)
print(flag)
这里就是先转字符,然后创建AES对象,这个参数就是key和mode两个变量,据我了解,这个mode好像有三种,还有CBC和CTR。都比这个ECB要复杂一点。最后直接decrypt就可以解密得到flag啦
最后附上flag:flag{924a9ab2163d390410d0a1f670}
总结:这里的新操作对我来说主要是强制转化函数,以及idc修改内容,还有远程动态调试,都可以稍微了解一下