0xgame re Xor::Random wp

参考官解

image-20241029215112336

image-20241029215247997

看到一大堆,别慌,冷静分析

主函数大概可以划分成三部分:先检查了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的值进行解密

image-20241029220107488

终端输入0xGame{aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}

V21点进去发现值

image-20241029220209267

v13点进去我们还能发现我们正常理解的顺序的值

image-20241029220252584

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就行