-
-
内存校验的一个诡异情况
-
发表于:
2010-10-21 00:01
4074
-
谁能告诉为什么下面的代码,编译成exe后 为什么每次输出的结果都不一样。。。
本人菜鸟 希望大侠给解决一下小弟的困惑。非常感谢。
#include "windows.h"
#include "stdio.h"
DWORD g_dwStartMain = 0;
DWORD g_dwEndMain = 0;
unsigned int GetCrc32(char* InStr,unsigned int len)
{
if (len <= 0)
return 0;
//生成Crc32的查询表
unsigned int Crc32Table[256] = {0};
for (unsigned int i = 0; i < 256; i++)
{
unsigned int Crc = i;
for (unsigned int j = 0; j < 8; j++)
{
if (Crc & 1)
Crc = (Crc >> 1) ^ 0xEDB88320;
else
Crc >>= 1;
}
Crc32Table[i] = Crc;
}
unsigned int Crc = 0xFFFFFFFF;
for(i=0; i<len; i++)
{
Crc = (Crc >> 8) ^ Crc32Table[(Crc & 0xFF) ^ InStr[i]];
}
Crc ^= 0xFFFFFFFF;
return Crc;
}
int main()
{
__asm mov g_dwStartMain, offset main+1
__asm mov g_dwEndMain, offset __end
printf("地址:%.8X, 长度:%.8X\r\n", g_dwStartMain, (unsigned int)(g_dwEndMain-g_dwStartMain));
printf ("%.8X\r\n", GetCrc32((char *)g_dwStartMain, (unsigned int)(g_dwEndMain-g_dwStartMain)));//
return 0;
char szUser[256] = {0};
char szPass[256] = {0};
__inputUser:
printf("请输入用户名(最少4位):");
scanf("%s", szUser);
while (strlen(szUser) < 4)
__asm jmp __inputUser;
printf("请输入密码:");
scanf("%s", szPass);
__end:
return 0;
}
这里说一下为什么会出现这种情况,这问题困扰了我好几天
问题出现在这句 Crc = (Crc >> 8) ^ Crc32Table[(Crc & 0xFF) ^ InStr[i]];
(Crc & 0xFF) 相当于一个 unsigned int,做异或运算的时候 InStr[i] 符合扩展成了一个DWORD(因为Instr是一个char数组是有符合的)
这样(Crc & 0xFF) ^ InStr[i] 就成了一个负数,这样Crc32Table数组就越界了(
注意是向前越界,而非常见的往后越界)
在Instr[i]前加一个(BYTE) 或者(unsigned char) 就不会出现这样的问题了。
有人会说 即使越界 那每次都越的一样 结果也应该一直才对。
其实每次越的界确实是一样的,但是由于是堆栈空间 里面的数据不确定的(为什么不确定呢?你去问盖茨吧 我也不知道为什么不确定) 所以每次运行数据很有可能就不一致。
[课程]Linux pwn 探索篇!