mirror of
https://github.com/atom0s/Steamless.git
synced 2024-12-19 23:07:41 +01:00
API: PE64 - Add new functionality to Pe64Helpers to recalculate a PE file checksum.
Unpackers: (x64) Ensure all unpacked files default to a checksum of 0. Unpackers: (x64) Add support for new RecalculateFileChecksum setting.
This commit is contained in:
parent
2380a4bd8a
commit
540b4b067f
3 changed files with 150 additions and 2 deletions
|
@ -27,6 +27,7 @@ namespace Steamless.API.PE64
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
@ -89,6 +90,97 @@ namespace Steamless.API.PE64
|
||||||
return GetStructure<NativeApi64.ImageSectionHeader64>(rawData, (int)dataOffset + (index * sectionSize));
|
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>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static bool UpdateFileChecksum(string path)
|
||||||
|
{
|
||||||
|
FileStream fStream = null;
|
||||||
|
var data = new byte[4];
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Open the file for reading/writing..
|
||||||
|
fStream = new FileStream(path, FileMode.Open, FileAccess.ReadWrite);
|
||||||
|
|
||||||
|
// Read the starting offset to the files NT headers..
|
||||||
|
fStream.Position = (int)Marshal.OffsetOf(typeof(NativeApi64.ImageDosHeader64), "e_lfanew");
|
||||||
|
fStream.Read(data, 0, 4);
|
||||||
|
|
||||||
|
var offset = BitConverter.ToUInt32(data, 0);
|
||||||
|
|
||||||
|
// Move to the files CheckSum position..
|
||||||
|
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 };
|
||||||
|
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
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
fStream?.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scans the given data for the given pattern.
|
/// Scans the given data for the given pattern.
|
||||||
///
|
///
|
||||||
|
|
|
@ -189,6 +189,13 @@ namespace Steamless.Unpacker.Variant30.x64
|
||||||
if (!this.Step6())
|
if (!this.Step6())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (this.Options.RecalculateFileChecksum)
|
||||||
|
{
|
||||||
|
this.Log("Step 7 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||||
|
if (!this.Step7())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -500,12 +507,13 @@ namespace Steamless.Unpacker.Variant30.x64
|
||||||
if (this.File.DosStubSize > 0)
|
if (this.File.DosStubSize > 0)
|
||||||
fStream.WriteBytes(this.File.DosStubData);
|
fStream.WriteBytes(this.File.DosStubData);
|
||||||
|
|
||||||
// Update the entry point of the file..
|
// Update the NT headers..
|
||||||
var ntHeaders = this.File.NtHeaders;
|
var ntHeaders = this.File.NtHeaders;
|
||||||
if (this.StubHeader.HasTlsCallback != 1)
|
if (this.StubHeader.HasTlsCallback != 1)
|
||||||
ntHeaders.OptionalHeader.AddressOfEntryPoint = this.StubHeader.OriginalEntryPoint;
|
ntHeaders.OptionalHeader.AddressOfEntryPoint = this.StubHeader.OriginalEntryPoint;
|
||||||
else
|
else
|
||||||
ntHeaders.OptionalHeader.AddressOfEntryPoint = this.TlsOepOverride;
|
ntHeaders.OptionalHeader.AddressOfEntryPoint = this.TlsOepOverride;
|
||||||
|
ntHeaders.OptionalHeader.CheckSum = 0;
|
||||||
this.File.NtHeaders = ntHeaders;
|
this.File.NtHeaders = ntHeaders;
|
||||||
|
|
||||||
// Write the NT headers to the file..
|
// Write the NT headers to the file..
|
||||||
|
@ -558,6 +566,26 @@ namespace Steamless.Unpacker.Variant30.x64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Step #7
|
||||||
|
///
|
||||||
|
/// Recalculate the file checksum.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool Step7()
|
||||||
|
{
|
||||||
|
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||||
|
if (!Pe64Helpers.UpdateFileChecksum(unpackedPath))
|
||||||
|
{
|
||||||
|
this.Log(" --> Error trying to recalculate unpacked file checksum!", LogMessageType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Log(" --> Unpacked file updated with new checksum!", LogMessageType.Success);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the Tls callback is being used as the Oep.
|
/// Gets or sets if the Tls callback is being used as the Oep.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -186,6 +186,13 @@ namespace Steamless.Unpacker.Variant31.x64
|
||||||
if (!this.Step6())
|
if (!this.Step6())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (this.Options.RecalculateFileChecksum)
|
||||||
|
{
|
||||||
|
this.Log("Step 7 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||||
|
if (!this.Step7())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -452,9 +459,10 @@ namespace Steamless.Unpacker.Variant31.x64
|
||||||
if (this.File.DosStubSize > 0)
|
if (this.File.DosStubSize > 0)
|
||||||
fStream.WriteBytes(this.File.DosStubData);
|
fStream.WriteBytes(this.File.DosStubData);
|
||||||
|
|
||||||
// Update the entry point of the file..
|
// Update the NT headers..
|
||||||
var ntHeaders = this.File.NtHeaders;
|
var ntHeaders = this.File.NtHeaders;
|
||||||
ntHeaders.OptionalHeader.AddressOfEntryPoint = (uint)this.StubHeader.OriginalEntryPoint;
|
ntHeaders.OptionalHeader.AddressOfEntryPoint = (uint)this.StubHeader.OriginalEntryPoint;
|
||||||
|
ntHeaders.OptionalHeader.CheckSum = 0;
|
||||||
this.File.NtHeaders = ntHeaders;
|
this.File.NtHeaders = ntHeaders;
|
||||||
|
|
||||||
// Write the NT headers to the file..
|
// Write the NT headers to the file..
|
||||||
|
@ -507,6 +515,26 @@ namespace Steamless.Unpacker.Variant31.x64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Step #7
|
||||||
|
///
|
||||||
|
/// Recalculate the file checksum.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool Step7()
|
||||||
|
{
|
||||||
|
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||||
|
if (!Pe64Helpers.UpdateFileChecksum(unpackedPath))
|
||||||
|
{
|
||||||
|
this.Log(" --> Error trying to recalculate unpacked file checksum!", LogMessageType.Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.Log(" --> Unpacked file updated with new checksum!", LogMessageType.Success);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets if the Tls callback is being used as the Oep.
|
/// Gets or sets if the Tls callback is being used as the Oep.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue