我想在C#中实现这个
我看过这里:
http://www.codeproject.com/KB/cpp/PEChecksum.aspx
并且我知道ImageHlp.dll MapFileAndCheckSum函数.
但是,出于各种原因,我想自己实现.
我发现的最好的是:
http://forum.sysinternals.com/optional-header-checksum-calculation_topic24214.html
但是,我不明白这个解释.任何人都可以澄清如何计算校验和吗?
谢谢!
更新
我从代码示例中,我不明白这意味着什么,以及如何将其转换为C#
sum -= sum < low 16 bits of CheckSum in file // 16-bit borrow sum -= low 16 bits of CheckSum in file sum -= sum < high 16 bits of CheckSum in file sum -= high 16 bits of CheckSum in file
更新#2
def generate_checksum(self): # This will make sure that the data representing the PE image # is updated with any changes that might have been made by # assigning values to header fields as those are not automatically # updated upon assignment. # self.__data__ = self.write() # Get the offset to the CheckSum field in the OptionalHeader # checksum_offset = self.OPTIONAL_HEADER.__file_offset__ + 0x40 # 64 checksum = 0 # Verify the data is dword-aligned. Add padding if needed # remainder = len(self.__data__) % 4 data = self.__data__ + ( '\0' * ((4-remainder) * ( remainder != 0 )) ) for i in range( len( data ) / 4 ): # Skip the checksum field # if i == checksum_offset / 4: continue dword = struct.unpack('I',data[ i*4 : i*4+4 ])[0] checksum = (checksum & 0xffffffff) + dword + (checksum>>32) if checksum > 2**32: checksum = (checksum & 0xffffffff) + (checksum >> 32) checksum = (checksum & 0xffff) + (checksum >> 16) checksum = (checksum) + (checksum >> 16) checksum = checksum & 0xffff # The length is the one of the original data,not the padded one # return checksum + len(self.__data__)
但是,它仍然不适合我 – 这是我对此代码的转换:
using System; using System.IO; namespace CheckSumTest { class Program { static void Main(string[] args) { var data = File.ReadAllBytes(@"c:\Windows\notepad.exe"); var PEStart = BitConverter.ToInt32(data,0x3c); var PECoffStart = PEStart + 4; var PEOptionalStart = PECoffStart + 20; var PECheckSum = PEOptionalStart + 64; var checkSumInFile = BitConverter.ToInt32(data,PECheckSum); Console.WriteLine(string.Format("{0:x}",checkSumInFile)); long checksum = 0; var remainder = data.Length % 4; if (remainder > 0) { Array.Resize(ref data,data.Length + (4 - remainder)); } var top = Math.Pow(2,32); for (int i = 0; i < data.Length / 4; i++) { if (i == PECheckSum / 4) { continue; } var dword = BitConverter.ToInt32(data,i * 4); checksum = (checksum & 0xffffffff) + dword + (checksum >> 32); if (checksum > top) { checksum = (checksum & 0xffffffff) + (checksum >> 32); } } checksum = (checksum & 0xffff) + (checksum >> 16); checksum = (checksum) + (checksum >> 16); checksum = checksum & 0xffff; checksum += (uint)data.Length; Console.WriteLine(string.Format("{0:x}",checksum)); Console.ReadKey(); } } }
谁能告诉我我在哪里傻了?
解决方法
好的,终于让它工作正常…我的问题是我使用的是不是uint !!!
因此,这段代码可以工作(假设数据是4字节对齐的,否则你必须将它填平一点) – 而PECheckSum是PE中CheckSum值的位置(在计算校验和时显然不会使用它! !)
因此,这段代码可以工作(假设数据是4字节对齐的,否则你必须将它填平一点) – 而PECheckSum是PE中CheckSum值的位置(在计算校验和时显然不会使用它! !)
static uint CalcCheckSum(byte[] data,int PECheckSum) { long checksum = 0; var top = Math.Pow(2,32); for (var i = 0; i < data.Length / 4; i++) { if (i == PECheckSum / 4) { continue; } var dword = BitConverter.ToUInt32(data,i * 4); checksum = (checksum & 0xffffffff) + dword + (checksum >> 32); if (checksum > top) { checksum = (checksum & 0xffffffff) + (checksum >> 32); } } checksum = (checksum & 0xffff) + (checksum >> 16); checksum = (checksum) + (checksum >> 16); checksum = checksum & 0xffff; checksum += (uint)data.Length; return (uint)checksum; }