1.观察主函数和说明:
总的要求就是要我们找出正确的密钥来解码给出的十六进制数据,主函数中通过传参的形式给四个key赋值,然后调用函数使用key1、key2和key3、key4分别将data解码传给msg1和msg2,我们的任务就是找到key输出正确的msg1和msg2.
2.转换:
该实验在于解码,我们可以先将截获的十六进制数据转化为字符串,来看看其中有什么
首先写了一个C语言程序进行转换
转化结果如下:
但结果似乎不是正确的
因为在原解码函数中将整型data数组强行转为char型指针进行转码这个指针从低位到高位进行遍历,但int型数据在内存中存储时又是倒着存的.
Eg:
故又写了下列程序
正确输出为:
2.解码:
接下来就是从这堆乱码中找出真实的数据
根据提示我们知道这段消息的开头是from:
一:找出msg1
①解析提取函数extract_message1,该函数调用两个参数start和stride,观察后我们发现该函数从char型data的第start+1个字符开始转换,每间隔stride-1个字符后跳过一个字符后再转换。再根据消息开头的from:和我们第一步转换出的正确的字符串可知start=9,stride=3。
(这里得出start和stride的值是一个个试的,具体操作可观看b站上学长的视频,这里不再赘述)
②验证①的猜想,我们先直接令start=9,stride=3,跑一下程序
结果如下:
可以看到,我们得到了正确的msg1。
③找出怎么令start=9,stride=3,可以看到他们两个的值都与dummy有关;
通过计算可以知道dummy=777=9+3*2^8,接下来我们就要想方法实现dummy=777,但我们又不能直接对dummy赋值,这样不符合不能修改源程序的要求,我们能赋值的是四个key。
然后注意到process_keys12这个函数,我们发现可以通过偏移key1的地址让其指向dummy的地址,然后令key2=777,将key2的值赋给偏移后的地址,如此我们就可以令dummy=777。
然后我们通过vs2022查看dummy和key1的地址,发现key1的地址比dummy的地址多了一个十六进制的0x60,即十进制的96,又int型数据在内存中占四个字节,故key1=-96/4,因此确定了key1=-24或-0x18,key2=777,接下来进行验证:
运行成功:
一:找出msg2
接下来的任务就是找出key3和key4,解出msg2。
①我们先看一下msg2是如何转化的,通过观察得出,msg2也是传入start和stride两个参数,然后进行转换,解析程序得出extract_message2 函数从data的第start个数据开始转换,每转化一次跳过stride-1个数据再转化。根据提示我们也知道msg2开始的数据也是from:,通过观察最开始的加密字符串我们可以确定start=9,stride=3,非常的巧合(或许是设计过的)。
②验证:跟msg1一样。同样我们先验证一下猜想
OK,we got everything.我们的猜想是正确的
③实现我们的猜想
同找msg1的过程,但我们要注意的是如何让程序输出msg2而不是msg1,我们看到在主函数让msg1为'\0',这时就不会输出msg1而输出msg2。接下来我们就要想办法是msg1='\0',这时就需要用到key3和key4。再看process_keys34这个函数中是如何处理key3和key4,可以看到指向key3的指针的指针在偏移后被赋值,我们肯定是不可以将其在偏移至dummy使start使data的最后一个数据,因为start和stride已经被赋值为了我们所需要的值,后续也没有start的再赋值了。因此呢,我们可以使msg1转化的第一个数据就是'\0',这样他就会停止转化,msg1就变成了'\0'。因此我们需要让指向key3的指针的指针偏移至data的第十个数据。并让其自己加上key4的值后变为'\0'。因此我们依旧使用vs进行地址查看,确认了key3=0x4FFB3926,key4=0x72464663-0x72004663,
即key4==0x460000。(此时查看地址时可以先令key3和key4随便一个值,在process_keys34处设一个断点,然后查看地址就好)
接下来我们输入key3和key4的值:
OK,we got everything。就此,我们成功完成了解码的全部过程,完成了项目。