我一直在重写一个程序,虽然它使用哈希来对文件进行指纹识别,但我已经使用 IDA 来查找执行哈希的函数以及它在将文件发送到哈希函数之前对文件执行的操作。
我只是对正在发生的事情有几个问题,我知道我可以像在 DLL 中一样简单地调用它,但我也想了解发生了什么。
unsigned int __cdecl newhash(int a1, unsigned int a2, int zero)
{
int content; // ebx@1
int v4; // ecx@1
int v5; // edx@1
int i; // eax@1
int v7; // ecx@2
unsigned int v8; // eax@2
int v9; // edx@2
int v10; // ecx@2
int v11; // eax@2
int v12; // edx@2
int v13; // ecx@2
int v14; // eax@2
unsigned int v15; // eax@3
int v16; // edx@15
int v17; // ecx@15
int v18; // eax@15
int v19; // edx@15
int v20; // ecx@15
int v21; // eax@15
int v22; // edx@15
unsigned int contentLength; // [sp+Ch] [bp-4h]@1
content = a1;
contentLength = a2;
v4 = -1640531527;
v5 = -1640531527;
for ( i = zero; contentLength >= 12; contentLength -= 12 )
{
v7 = (*(_BYTE *)(content + 7) << 24)
+ (*(_BYTE *)(content + 6) << 16)
+ (*(_BYTE *)(content + 5) << 8)
+ *(_BYTE *)(content + 4)
+ v4;
v8 = (*(_BYTE *)(content + 11) << 24)
+ (*(_BYTE *)(content + 10) << 16)
+ (*(_BYTE *)(content + 9) << 8)
+ *(_BYTE *)(content + 8)
+ i;
v9 = (v8 >> 13) ^ ((*(_BYTE *)(content + 3) << 24)
+ (*(_BYTE *)(content + 2) << 16)
+ (*(_BYTE *)(content + 1) << 8)
+ *(_BYTE *)content
+ v5
- v7
- v8);
v10 = (v9 << 8) ^ (v7 - v8 - v9);
v11 = ((unsigned int)v10 >> 13) ^ (v8 - v9 - v10);
v12 = ((unsigned int)v11 >> 12) ^ (v9 - v10 - v11);
v13 = (v12 << 16) ^ (v10 - v11 - v12);
v14 = ((unsigned int)v13 >> 5) ^ (v11 - v12 - v13);
v5 = ((unsigned int)v14 >> 3) ^ (v12 - v13 - v14);
v4 = (v5 << 10) ^ (v13 - v14 - v5);
i = ((unsigned int)v4 >> 15) ^ (v14 - v5 - v4);
content += 12;
}
v15 = a2 + i;
switch ( contentLength )
{
case 0xBu:
v15 += *(_BYTE *)(content + 10) << 24;
goto LABEL_5;
case 0xAu:
LABEL_5:
v15 += *(_BYTE *)(content + 9) << 16;
goto LABEL_6;
case 9u:
LABEL_6:
v15 += *(_BYTE *)(content + 8) << 8;
goto LABEL_7;
case 8u:
LABEL_7:
v4 += *(_BYTE *)(content + 7) << 24;
goto LABEL_8;
case 7u:
LABEL_8:
v4 += *(_BYTE *)(content + 6) << 16;
goto LABEL_9;
case 6u:
LABEL_9:
v4 += *(_BYTE *)(content + 5) << 8;
goto LABEL_10;
case 5u:
LABEL_10:
v4 += *(_BYTE *)(content + 4);
goto LABEL_11;
case 4u:
LABEL_11:
v5 += *(_BYTE *)(content + 3) << 24;
goto LABEL_12;
case 3u:
LABEL_12:
v5 += *(_BYTE *)(content + 2) << 16;
goto LABEL_13;
case 2u:
LABEL_13:
v5 += *(_BYTE *)(content + 1) << 8;
goto LABEL_14;
case 1u:
LABEL_14:
v5 += *(_BYTE *)content;
break;
default:
break;
}
v16 = (v15 >> 13) ^ (v5 - v4 - v15);
v17 = (v16 << 8) ^ (v4 - v15 - v16);
v18 = ((unsigned int)v17 >> 13) ^ (v15 - v16 - v17);
v19 = ((unsigned int)v18 >> 12) ^ (v16 - v17 - v18);
v20 = (v19 << 16) ^ (v17 - v18 - v19);
v21 = ((unsigned int)v20 >> 5) ^ (v18 - v19 - v20);
v22 = ((unsigned int)v21 >> 3) ^ (v19 - v20 - v21);
return (((v22 << 10) ^
(unsigned int)(v20 - v21 - v22)) >> 15) ^
(v21 - v22 - ((v22 << 10) ^ (v20 - v21 - v22)));
}
a1 是一个地址位置 a2 是散列零的文件长度我重命名了因为它总是出于任何原因发送零。
现在的问题:
- 首先也是最重要的,这是一个像CRC这样的标准算法吗?
- v4 和 v5 变量是否有理由为 -1640531527?
(*(_BYTE *)(content + 7) << 24)
不是一个字节只有8位的目的是什么,所以每次都是0吗?我查了一下操作的顺序,似乎首先是转换,然后是位操作,所以这意味着它将它转换为文件中的第 8 个字节并将其位移 24 位,对吗?为什么?- 为什么有些位是有符号的,有些是无符号的,如果混合会改变结果吗?
这些是我的大部分问题,我知道它正在遍历所有字节并计算出文件的“哈希”,我知道 switch case 正在处理文件不能被完全整除的情况到 12. 我想一旦我理解了按位运算背后的逻辑就会更清楚。