#if 0
[URL]http://www.opencjk.org/~scz/windows/200701102106.txt[/URL]
在某些时候可能你并不想用imagehlp!CheckSumMappedFile()去计算PE文件校验和,
这个函数或许用得上。网上ASM实现很多,C实现不好找吧。
最近因为要写个程序自动剁tcpip.sys,顺便折腾了一下PE文件校验和的计算。
#endif
/*
* RFC 1141 : Incremental Updating of the Internet Checksum
*
* 2007-01-10 21:06 scz
*
* PE首部的CheckSum是4字节的DWORD型,计算方法与IP首部校验和非常类似,其C语
* 言实现一直不太好找,这里给一个基于IP首部校验和C实现修改后的函数。已经处
* 理了奇偶。形参base_sum为旧的CheckSum,无论原值是否正确,不必将内存中的
* 该字段清零再计算,如果清零,则base_sum也要赋成零再计算。
*
* 2007-01-29 15:30 scz
*
* 更正了一个BUG,注意sum的数据类型是64-bits的。
*/
static unsigned int pe_cksum
(
unsigned short int *addr,
unsigned int len,
unsigned long long base_sum
)
{
unsigned int nleft = len;
/*
* 这里不同,反码加一即取负,这种变态写法仅仅是为了避免一个编译警告。
*
* LONGLONG
* ULONG64
* unsigned long long
*/
unsigned long long sum = ~base_sum + 1;
unsigned short int *w = addr;
unsigned short int answer = 0;
/*
* Our algorithm is simple, using a 32 bit accumulator (sum), we add
* sequential 16 bit words to it, and at the end, fold back all the
* carry bits from the top 16 bits into the lower 16 bits.
*/
while ( nleft > 1 )
{
sum += *w++;
nleft -= 2;
}
/*
* mop up an odd byte, if necessary
*/
if ( 1 == nleft )
{
*( unsigned char * )( &answer ) = *( unsigned char * )w ;
sum += answer;
}
/*
* add back carry outs from top 16 bits to low 16 bits
*
* add hi 16 to low 16
*/
sum = ( sum >> 16 ) + ( sum & 0xFFFF );
/*
* add carry
*/
sum += ( sum >> 16 );
/*
* truncate to 16 bits
*/
answer = ( unsigned short )( sum & 0xFFFF );
/*
* 这里不同
*
* add len
*/
sum = answer + len;
return( ( unsigned int )sum );
} /* end of pe_cksum */