接下来,函数将连续调用两次sub_40196E()。第一次调用的参数为栈上拷贝的0x603170处的16字节数据,第二次调用的参数则涉及我们的输入&s[0]及&s[16]。最终,这个函数会调用到具有明显AES加密特征的sub_401828()。这个函数遵循初始变换、9轮循环运算和最终运算的过程,其调用的几个函数也符合AES内部的逻辑。
在sub_402219()的最后部分,加密后的输入将与0x6030A0处的数据进行比对。那么,密钥——存放在0x603170处的数据是什么呢?我们回到主函数,在调用sub_402219()之前,会先调用sub_40207B()。这个函数的主要操作是多次调用sub_401CF9(),传入的参数位于data段上。
仔细观察sub_401CF9()开头的四个常数,我们可以推断出这应该是md5算法的迹象。深入查看程序逻辑,确实如此。sub_402219()的运作逻辑变得清晰:它执行多轮md5哈希,并将结果存储在0x603170处。通过动态调试,我们可以获得这里的具体数据。
由于AES是一种对称加密算法,现在我们已经掌握了密钥(0x603170)和密文(0x6030A0),可以直接使用Python内置的密码学库来获取flag。