0xgame re XorRandom wp
0xgame re Xor::Random wp
参考官解
看到一大堆,别慌,冷静分析
主函数大概可以划分成三部分:先检查了flag的格式和长度,之后⽣成随机数 v21 异或加密⼀边检查。注意密钥从 v21和 重点说⼀下中间随机数的部分。
我们如果仔细看了这些代码,就知道中间只是个异或,那么密文在哪,我们沿着算法网上找就能找到v13,不过还不能直接用(当然c语言可以直接用这个),这是小端存储的也就是说0c,4f,….,存储的,建议先去了解
那么问题就是中间的v21了,他是个(伪)随机数,只要设定了种子,每次出来的结果都是一样的(当然受到版本的影响)
inited = init_random();
std::string::basic_string(v20, v14);
v6 = check((__int64)v20);
std::string::~string(v20);
if ( v6 )
{
srand(0x1919810u);
inited = rand();
}
v21 = rand();
分析这段我们就知道,先会生成一个随机数,然后根据check,v6(点进去check,我们发现check肯定是0),所以v6的那个if肯定不会执行,下面生成的随机数会给v21,上面的inited用不到,那样我们只要得到v21就能解密了,有两种方案:
这里主要的加密方法是异或,异或算法的特性是ab=c bc=a,不懂自己查,所以我们把源码还原出来再执行就行
方法一:静态分析
我们顺着逻辑写一遍c代码就行
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main() {
unsigned char num, key;
unsigned char* array;
unsigned long long v13[4];
v13[0] = 0x1221164E1F104F0C;
v13[1] = 0x171F240A4B10244B;
v13[2] = 0x1A2C5C2108074F09;
v13[3] = 99338668810000;
srand(0x77);
num = rand();
num = rand();
array = (unsigned char*)v13;
for (int i = 0; i <= 29; i++){
key = (i % 2 != 0 ? num : num + 3);
array[i] ^= key;
}
printf("0xGame{%s}", array);
return 0;
}
num = rand();
num = rand();这里要Rand两次
在 srand()
设置固定的种子后,rand()
会基于该种子生成一个伪随机数序列。每次调用 rand()
,都会按照这个序列的顺序返回下一个数。即使种子相同,不同调用顺序下的结果依然会不一样,因为 rand()
是在一个依次递进的伪随机数序列中产生值。
方法⼆:动态调试直接拿密钥
我们可以动态调试拿到v21的值进行解密
终端输入0xGame{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}
V21点进去发现值
v13点进去我们还能发现我们正常理解的顺序的值
f = '0xGame{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}'
enc = [
0x0C, 0x4F, 0x10, 0x1F, 0x4E, 0x16, 0x21, 0x12, 0x4B, 0x24,
0x10, 0x4B, 0x0A, 0x24, 0x1F, 0x17, 0x09, 0x4F, 0x07, 0x08,
0x21, 0x5C, 0x2C, 0x1A, 0x10, 0x1F, 0x11, 0x16, 0x59, 0x5A
]
key = 0x7B
for i in range(len(enc)):
if i & 1:
print(chr(enc[i] ^ key), end='')
else:
print(chr(enc[i] ^ key + 3), end='')
r4nd0m_i5_n0t_alw4ys_'Random'!
加上0xgame就行
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 Matriy
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果