1
0
Fork 0
mirror of https://github.com/atom0s/Steamless.git synced 2024-12-22 23:17:40 +01:00

PE32: Replace manual PE checksum calculations with Win32 API call instead.

PE64: Replace manual PE checksum calculations with Win32 API call instead.

I was trying to avoid using Win32 API calls in this project for the most part, however, this calculation has multiple conditions that can alter its result. Steamless was only producing proper checksums about 40% of the time as a result of this. Instead, the project will now use the system API call 'MapFileAndCheckSum' to calculate the checksum properly.
This commit is contained in:
atom0s 2022-09-23 15:57:55 -07:00
parent 51be8ca795
commit 411f4f711c
No known key found for this signature in database
GPG key ID: 37D5FD3494D79AF8
3 changed files with 16 additions and 106 deletions

View file

@ -90,49 +90,6 @@ namespace Steamless.API.PE32
return GetStructure<NativeApi32.ImageSectionHeader32>(rawData, dataOffset + (index * sectionSize));
}
/// <summary>
/// Calculates the PE checksum of the opened file. (OptionalHeader.Checksum should be 0 before calling this!)
/// </summary>
/// <param name="fStream"></param>
/// <returns></returns>
private static byte[] CalculateChecksum(FileStream fStream)
{
fStream.Position = 0;
var dataSize = fStream.Length;
var totalWords = dataSize / 2;
var sumTotal = 0;
// Process the file data in uint16_t chunks..
while (totalWords > 0)
{
var sumChunk = 0;
var chunkWords = totalWords;
// Prepare next chunk size..
if (chunkWords > UInt16.MaxValue)
chunkWords = UInt16.MaxValue;
totalWords -= chunkWords;
do
{
var data = new byte[2];
fStream.Read(data, 0, 2);
sumChunk += BitConverter.ToUInt16(data, 0);
} while (--chunkWords != 0);
sumTotal += (sumChunk >> 16) + (sumChunk & 0xFFFF);
}
if ((dataSize % 2) != 0)
sumTotal += fStream.ReadByte();
var checksum = (uint)(((sumTotal >> 16) + (sumTotal & 0xFFFF)) + dataSize);
return BitConverter.GetBytes(checksum);
}
/// <summary>
/// Updates the given files PE checksum value. (Path is assumed to be a 32bit PE file.)
/// </summary>
@ -140,6 +97,11 @@ namespace Steamless.API.PE32
/// <returns></returns>
public static bool UpdateFileChecksum(string path)
{
// Obtain the proper checksum for the file..
var ret = NativeApi32.MapFileAndCheckSum(path, out uint HeaderSum, out uint Checksum);
if (ret != 0)
return false;
FileStream fStream = null;
var data = new byte[4];
@ -158,17 +120,10 @@ namespace Steamless.API.PE32
offset += 4 + (uint)Marshal.SizeOf(typeof(NativeApi32.ImageFileHeader32)) + (uint)Marshal.OffsetOf(typeof(NativeApi32.ImageOptionalHeader32), "CheckSum").ToInt32();
fStream.Position = offset;
// Ensure the checksum is 0 to start..
data = new byte[4] { 0, 0, 0, 0 };
// Overwrite the file checksum..
data = BitConverter.GetBytes(Checksum);
fStream.Write(data, 0, 4);
// Calculate the new checksum..
var checksum = CalculateChecksum(fStream);
// Update the checksum value..
fStream.Position = offset;
fStream.Write(checksum, 0, 4);
return true;
}
catch

View file

@ -90,49 +90,6 @@ namespace Steamless.API.PE64
return GetStructure<NativeApi64.ImageSectionHeader64>(rawData, (int)dataOffset + (index * sectionSize));
}
/// <summary>
/// Calculates the PE checksum of the opened file. (OptionalHeader.Checksum should be 0 before calling this!)
/// </summary>
/// <param name="fStream"></param>
/// <returns></returns>
private static byte[] CalculateChecksum(FileStream fStream)
{
fStream.Position = 0;
var dataSize = fStream.Length;
var totalWords = dataSize / 2;
var sumTotal = 0;
// Process the file data in uint16_t chunks..
while (totalWords > 0)
{
var sumChunk = 0;
var chunkWords = totalWords;
// Prepare next chunk size..
if (chunkWords > UInt16.MaxValue)
chunkWords = UInt16.MaxValue;
totalWords -= chunkWords;
do
{
var data = new byte[2];
fStream.Read(data, 0, 2);
sumChunk += BitConverter.ToUInt16(data, 0);
} while (--chunkWords != 0);
sumTotal += (sumChunk >> 16) + (sumChunk & 0xFFFF);
}
if ((dataSize % 2) != 0)
sumTotal += fStream.ReadByte();
var checksum = (uint)(((sumTotal >> 16) + (sumTotal & 0xFFFF)) + dataSize);
return BitConverter.GetBytes(checksum);
}
/// <summary>
/// Updates the given files PE checksum value. (Path is assumed to be a 32bit PE file.)
/// </summary>
@ -140,6 +97,11 @@ namespace Steamless.API.PE64
/// <returns></returns>
public static bool UpdateFileChecksum(string path)
{
// Obtain the proper checksum for the file..
var ret = NativeApi64.MapFileAndCheckSum(path, out uint HeaderSum, out uint Checksum);
if (ret != 0)
return false;
FileStream fStream = null;
var data = new byte[4];
@ -158,17 +120,10 @@ namespace Steamless.API.PE64
offset += 4 + (uint)Marshal.SizeOf(typeof(NativeApi64.ImageFileHeader64)) + (uint)Marshal.OffsetOf(typeof(NativeApi64.ImageOptionalHeader64), "CheckSum").ToInt32();
fStream.Position = offset;
// Ensure the checksum is 0 to start..
data = new byte[4] { 0, 0, 0, 0 };
// Overwrite the file checksum..
data = BitConverter.GetBytes(Checksum);
fStream.Write(data, 0, 4);
// Calculate the new checksum..
var checksum = CalculateChecksum(fStream);
// Update the checksum value..
fStream.Position = offset;
fStream.Write(checksum, 0, 4);
return true;
}
catch

View file

@ -36,5 +36,5 @@ using System.Runtime.InteropServices;
[assembly: AssemblyCulture("")]
[assembly: ComVisible(false)]
[assembly: Guid("56c95629-3b34-47fe-b988-04274409294f")]
[assembly: AssemblyVersion("1.0.0.5")]
[assembly: AssemblyFileVersion("1.0.0.5")]
[assembly: AssemblyVersion("1.0.0.6")]
[assembly: AssemblyFileVersion("1.0.0.6")]