I would like to implement this in C #
I looked here: http://www.codeproject.com/KB/cpp/PEChecksum.aspx
And I know about the ImageHlp.dll function MapFileAndCheckSum.
However, for various reasons, I would like to implement this myself.
The best I have found is here: http://forum.sysinternals.com/optional-header-checksum-calculation_topic24214.html
But I do not understand the explanation. Can someone clarify how the checksum is calculated?
Thanks!
Update
I am from the sample code, I do not understand what this means, and how to translate it to 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
Update # 2
Thanks, stumbled upon some Python code, which is also similar here
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__)
However, it still does not work for me - here is my conversion of this code:
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(); } } }
Can anyone tell me where I am stupid?