mirror of
https://github.com/atom0s/Steamless.git
synced 2024-12-19 23:07:41 +01:00
Core: Fix typo with new ZeroDosStubData option checkbox using wrong field bool.
API: Add new option RecalculateFileChecksum to allow unpacked files to have their PE checksum recalculated. API: PE32 - Add new functionality to Pe32Helpers to recalculate a PE file checksum. Unpackers: (x86) Add support for new RecalculateFileChecksum setting. 64bit handling to be added soon.
This commit is contained in:
parent
12c312b4db
commit
7cb8eaf613
8 changed files with 243 additions and 2 deletions
|
@ -39,6 +39,7 @@ namespace Steamless.API.Model
|
|||
this.UseExperimentalFeatures = false;
|
||||
this.DontRealignSections = true;
|
||||
this.ZeroDosStubData = true;
|
||||
this.RecalculateFileChecksum = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -103,5 +104,14 @@ namespace Steamless.API.Model
|
|||
get => this.Get<bool>("ZeroDosStubData");
|
||||
set => this.Set("ZeroDosStubData", value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets if the file checksum should be recalculated.
|
||||
/// </summary>
|
||||
public bool RecalculateFileChecksum
|
||||
{
|
||||
get => this.Get<bool>("RecalculateFileChecksum");
|
||||
set => this.Set("RecalculateFileChecksum", value);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ namespace Steamless.API.PE32
|
|||
{
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -89,6 +90,97 @@ 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>
|
||||
/// <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(NativeApi32.ImageDosHeader32), "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(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 };
|
||||
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>
|
||||
/// Scans the given data for the given pattern.
|
||||
///
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace Steamless.Unpacker.Variant10.x86
|
|||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
[SteamlessApiVersion(1, 0)]
|
||||
public class Main : SteamlessPlugin
|
||||
|
@ -149,6 +150,13 @@ namespace Steamless.Unpacker.Variant10.x86
|
|||
if (!this.Step3())
|
||||
return false;
|
||||
|
||||
if (this.Options.RecalculateFileChecksum)
|
||||
{
|
||||
this.Log("Step 4 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||
if (!this.Step4())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -267,9 +275,10 @@ namespace Steamless.Unpacker.Variant10.x86
|
|||
if (this.File.DosStubSize > 0)
|
||||
fStream.WriteBytes(this.File.DosStubData);
|
||||
|
||||
// Update the entry point of the file..
|
||||
// Update the entry point and checksum of the file..
|
||||
var ntHeaders = this.File.NtHeaders;
|
||||
ntHeaders.OptionalHeader.AddressOfEntryPoint = this.OriginalEntryPoint;
|
||||
ntHeaders.OptionalHeader.CheckSum = 0;
|
||||
this.File.NtHeaders = ntHeaders;
|
||||
|
||||
// Write the NT headers to the file..
|
||||
|
@ -318,6 +327,26 @@ namespace Steamless.Unpacker.Variant10.x86
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step #4
|
||||
///
|
||||
/// Recalculate the file checksum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool Step4()
|
||||
{
|
||||
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||
if (!Pe32Helpers.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>
|
||||
/// Gets or sets the Steamless options this file was requested to process with.
|
||||
/// </summary>
|
||||
|
|
|
@ -159,6 +159,13 @@ namespace Steamless.Unpacker.Variant20.x86
|
|||
if (!this.Step4())
|
||||
return false;
|
||||
|
||||
if (this.Options.RecalculateFileChecksum)
|
||||
{
|
||||
this.Log("Step 5 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||
if (!this.Step5())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -381,6 +388,26 @@ namespace Steamless.Unpacker.Variant20.x86
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step #5
|
||||
///
|
||||
/// Recalculate the file checksum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool Step5()
|
||||
{
|
||||
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||
if (!Pe32Helpers.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>
|
||||
/// Disassembles the file to locate the needed DRM header information.
|
||||
/// </summary>
|
||||
|
|
|
@ -169,6 +169,13 @@ namespace Steamless.Unpacker.Variant21.x86
|
|||
if (!this.Step6())
|
||||
return false;
|
||||
|
||||
if (this.Options.RecalculateFileChecksum)
|
||||
{
|
||||
this.Log("Step 7 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||
if (!this.Step7())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -508,6 +515,26 @@ namespace Steamless.Unpacker.Variant21.x86
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step #7
|
||||
///
|
||||
/// Recalculate the file checksum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool Step7()
|
||||
{
|
||||
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||
if (!Pe32Helpers.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>
|
||||
/// Disassembles the file to locate the needed DRM header information.
|
||||
/// </summary>
|
||||
|
|
|
@ -193,6 +193,13 @@ namespace Steamless.Unpacker.Variant30.x86
|
|||
if (!this.Step6())
|
||||
return false;
|
||||
|
||||
if (this.Options.RecalculateFileChecksum)
|
||||
{
|
||||
this.Log("Step 7 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||
if (!this.Step7())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -511,6 +518,26 @@ namespace Steamless.Unpacker.Variant30.x86
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step #7
|
||||
///
|
||||
/// Recalculate the file checksum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool Step7()
|
||||
{
|
||||
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||
if (!Pe32Helpers.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>
|
||||
/// Gets or sets if the Tls callback is being used as the Oep.
|
||||
/// </summary>
|
||||
|
|
|
@ -192,6 +192,13 @@ namespace Steamless.Unpacker.Variant31.x86
|
|||
if (!this.Step6())
|
||||
return false;
|
||||
|
||||
if (this.Options.RecalculateFileChecksum)
|
||||
{
|
||||
this.Log("Step 7 - Rebuild unpacked file checksum.", LogMessageType.Information);
|
||||
if (!this.Step7())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -507,6 +514,26 @@ namespace Steamless.Unpacker.Variant31.x86
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Step #7
|
||||
///
|
||||
/// Recalculate the file checksum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private bool Step7()
|
||||
{
|
||||
var unpackedPath = this.File.FilePath + ".unpacked.exe";
|
||||
if (!Pe32Helpers.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>
|
||||
/// Gets or sets if the Tls callback is being used as the Oep.
|
||||
/// </summary>
|
||||
|
|
|
@ -86,6 +86,7 @@
|
|||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<CheckBox Grid.Row="0" Content="Verbose Output" Margin="2" ToolTip="If enabled, Steamless will allow logging of debug messages." IsChecked="{Binding Options.VerboseOutput}" />
|
||||
<CheckBox Grid.Row="1" Content="Keep Bind Section" Margin="2" ToolTip="The bind section should be kept within the file after unpacking." IsChecked="{Binding Options.KeepBindSection}" />
|
||||
|
@ -93,7 +94,8 @@
|
|||
<CheckBox Grid.Row="3" Content="Dump SteamDRMP.dll To Disk" Margin="2" ToolTip="Dumps the SteamDRMP.dll to disk where the target file is located." IsChecked="{Binding Options.DumpSteamDrmpToDisk}" />
|
||||
<CheckBox Grid.Row="4" Content="Use Experimental Features" Margin="2" ToolTip="Enables the use of experimental features." IsChecked="{Binding Options.UseExperimentalFeatures}" />
|
||||
<CheckBox Grid.Row="5" Content="Don't Realign Sections" Margin="2" ToolTip="Disables realignment of sections when unpacking." IsChecked="{Binding Options.DontRealignSections}" />
|
||||
<CheckBox Grid.Row="6" Content="Zero DOS Stub Data" Margin="2" ToolTip="Sets the DOS stub data to 00's." IsChecked="{Binding Options.DontRealignSections}" />
|
||||
<CheckBox Grid.Row="6" Content="Zero DOS Stub Data" Margin="2" ToolTip="Sets the DOS stub data to 00's." IsChecked="{Binding Options.ZeroDosStubData}" />
|
||||
<CheckBox Grid.Row="7" Content="Recalculate File Checksum" Margin="2" ToolTip="Recalculates the file checksum in the unpacked file." IsChecked="{Binding Options.RecalculateFileChecksum}" />
|
||||
</Grid>
|
||||
</GroupBox>
|
||||
|
||||
|
|
Loading…
Reference in a new issue