/// <summary> /// Gets the SteamStub header size from the given file. /// </summary> /// <param name="f"></param> /// <returns></returns> private uint GetHeaderSize(Pe32File f) { // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v3.x signature.. var varient = Pe32Helpers.FindPattern(bind, "E8 00 00 00 00 50 53 51 52 56 57 55 8B 44 24 1C 2D 05 00 00 00 8B CC 83 E4 F0 51 51 51 50"); if (varient == 0) { return(0); } // Attempt to determine the varient version.. uint headerSize; var offset = Pe32Helpers.FindPattern(bind, "55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 68"); if (offset == 0) { offset = Pe32Helpers.FindPattern(bind, "55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 8D 83"); if (offset == 0) { return(0); } headerSize = (uint)BitConverter.ToInt32(bind, (int)offset + 22); } else { headerSize = (uint)BitConverter.ToInt32(bind, (int)offset + 16); } return(headerSize); }
/// <summary> /// Processing function called when a file is being unpacked. Allows plugins to check the file /// and see if it can handle the file for its intended purpose. /// </summary> /// <param name="file"></param> /// <returns></returns> public override bool CanProcessFile(string file) { try { // Load the file.. var f = new Pe32File(file); if (!f.Parse() || f.IsFile64Bit() || !f.HasSection(".bind")) { return(false); } // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v1.x signature.. var variant = Pe32Helpers.FindPattern(bind, "60 81 EC 00 10 00 00 BE ?? ?? ?? ?? B9 6A"); if (variant == -1) { return(false); } return(true); } catch { return(false); } }
/// <summary> /// Processing function called when a file is being unpacked. Allows plugins to check the file /// and see if it can handle the file for its intended purpose. /// </summary> /// <param name="file"></param> /// <returns></returns> public override bool CanProcessFile(string file) { try { // Load the file.. var f = new Pe32File(file); if (!f.Parse()) { this.Log("Failed to parse PE", LogMessageType.Information); return(false); } if (f.IsFile64Bit()) { this.Log("Is not 32bit", LogMessageType.Information); return(false); } if (!f.HasSection(".bind")) { this.Log("No bind section", LogMessageType.Information); return(false); } // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v2.x signature.. return(Pe32Helpers.FindPattern(bind, "53 51 52 56 57 55 8B EC 81 EC 00 10 00 00 C7") > 0); } catch (Exception e) { this.Log(e.ToString(), LogMessageType.Warning); return(false); } }
/// <summary> /// Step #4 /// /// Scan, dump and pull needed offsets from within the SteamDRMP.dll file. /// </summary> /// <returns></returns> private bool Step4() { // Scan for the needed data by a known pattern for the block of offset data.. var drmpOffset = Pe32Helpers.FindPattern(this.SteamDrmpData, "8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8D ?? ?? ?? ?? ?? 05"); if (drmpOffset == 0) { // Fall-back pattern scan for certain files that fail with the above pattern.. drmpOffset = Pe32Helpers.FindPattern(this.SteamDrmpData, "8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B"); if (drmpOffset == 0) { return(false); } } // Copy the block of data from the SteamDRMP.dll data.. var drmpOffsetData = new byte[1024]; Array.Copy(this.SteamDrmpData, drmpOffset, drmpOffsetData, 0, 1024); // Obtain the offsets from the file data.. var drmpOffsets = this.GetSteamDrmpOffsets(drmpOffsetData); if (drmpOffsets.Count != 8) { return(false); } // Store the offsets.. this.SteamDrmpOffsets = drmpOffsets; return(true); }
/// <summary> /// Step #1 /// /// Read, decode and validate the SteamStub DRM header. /// </summary> /// <returns></returns> private bool Step1() { // Obtain the bind section.. var section = this.File.GetSection(".bind"); if (!section.IsValid) { return(false); } // Find the header information from the unpacker call.. var bind = this.File.GetSectionData(".bind"); var offset = Pe32Helpers.FindPattern(bind, "60 81 EC 00 10 00 00 BE ?? ?? ?? ?? B9 6A"); if (offset == -1) { return(false); } // Read the needed header information.. var headerPointer = BitConverter.ToUInt32(bind, (int)offset + 8); var headerSize = BitConverter.ToUInt32(bind, (int)offset + 13) * 4; // Calculate the file offset from the pointer.. var fileOffset = this.File.GetFileOffsetFromRva(headerPointer - this.File.NtHeaders.OptionalHeader.ImageBase); // Read the header data.. var headerData = new byte[headerSize]; Array.Copy(this.File.FileData, fileOffset, headerData, 0, headerSize); // Decrypt the header data.. for (var x = 0; x < headerSize; x++) { headerData[x] ^= (byte)(x * x); } // Store the header and validate it.. this.StubHeader = Pe32Helpers.GetStructure <SteamStub32Var10Header>(headerData); // Validate the header via the unpacker function matching the file entry point.. if (this.StubHeader.BindFunction - this.File.NtHeaders.OptionalHeader.ImageBase != this.File.NtHeaders.OptionalHeader.AddressOfEntryPoint) { return(false); } // Find the OEP from the unpacker function.. offset = Pe32Helpers.FindPattern(bind, "61 B8 ?? ?? ?? ?? FF E0"); if (offset == -1) { return(false); } // Read and store the real OEP.. this.OriginalEntryPoint = BitConverter.ToUInt32(bind, (int)offset + 2) - this.File.NtHeaders.OptionalHeader.ImageBase; return(true); }
/// <summary> /// Processing function called when a file is being unpacked. Allows plugins to check the file /// and see if it can handle the file for its intended purpose. /// </summary> /// <param name="file"></param> /// <returns></returns> public override bool CanProcessFile(string file) { try { // Load the file.. var f = new Pe32File(file); if (!f.Parse() || f.IsFile64Bit() || !f.HasSection(".bind")) { return(false); } // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v3.x signature.. var varient = Pe32Helpers.FindPattern(bind, "E8 00 00 00 00 50 53 51 52 56 57 55 8B 44 24 1C 2D 05 00 00 00 8B CC 83 E4 F0 51 51 51 50"); if (varient == 0) { return(false); } // Version patterns.. var varientPatterns = new List <KeyValuePair <string, int> > { new KeyValuePair <string, int>("55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 68", 0x10), // v3.1 [Original version?] new KeyValuePair <string, int>("55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 8D 83", 0x16), // v3.1.1 [Newer, 3.1.1? (Seen 2015?)] new KeyValuePair <string, int>("55 8B EC 81 EC ?? ?? ?? ?? 56 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 8D", 0x10) // v3.1.2 [Newer, 3.1.2? (Seen late 2017.)] }; var headerSize = 0; uint offset = 0; foreach (var p in varientPatterns) { offset = Pe32Helpers.FindPattern(bind, p.Key); if (offset <= 0) { continue; } headerSize = BitConverter.ToInt32(bind, (int)offset + p.Value); break; } // Ensure valid data was found.. if (offset == 0 || headerSize == 0) { return(false); } return(headerSize == 0xF0); } catch { return(false); } }
/// <summary> /// Processing function called when a file is being unpacked. Allows plugins to check the file /// and see if it can handle the file for its intended purpose. /// </summary> /// <param name="file"></param> /// <returns></returns> public override bool CanProcessFile(string file) { try { // Load the file.. var f = new Pe32File(file); if (!f.Parse() || f.IsFile64Bit() || !f.HasSection(".bind")) { return(false); } // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v3.x signature.. var varient = Pe32Helpers.FindPattern(bind, "E8 00 00 00 00 50 53 51 52 56 57 55 8B 44 24 1C 2D 05 00 00 00 8B CC 83 E4 F0 51 51 51 50"); if (varient == 0) { return(false); } // Attempt to determine the varient version.. int headerSize; var offset = Pe32Helpers.FindPattern(bind, "55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 68"); if (offset == 0) { offset = Pe32Helpers.FindPattern(bind, "55 8B EC 81 EC ?? ?? ?? ?? 53 ?? ?? ?? ?? ?? 8D 83"); if (offset == 0) { return(false); } headerSize = BitConverter.ToInt32(bind, (int)offset + 22); } else { headerSize = BitConverter.ToInt32(bind, (int)offset + 16); } return(headerSize == 0xF0); } catch { return(false); } }
/// <summary> /// Step #4 /// /// Scan, dump and pull needed offsets from within the SteamDRMP.dll file. /// </summary> /// <returns></returns> private bool Step4() { // Scan for the needed data by a known pattern for the block of offset data.. var drmpOffset = Pe32Helpers.FindPattern(this.SteamDrmpData, "8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8D ?? ?? ?? ?? ?? 05"); if (drmpOffset == 0) { // Fall-back pattern scan for certain files that fail with the above pattern.. drmpOffset = Pe32Helpers.FindPattern(this.SteamDrmpData, "8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B"); if (drmpOffset == 0) { // Fall-back pattern (2).. (Seen in some v2 variants.) drmpOffset = Pe32Helpers.FindPattern(this.SteamDrmpData, "8B ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? A3 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? A3 ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? A3 ?? ?? ?? ?? 8B"); if (drmpOffset == 0) { return(false); } // Use fallback offsets if this worked.. this.UseFallbackDrmpOffsets = true; } } // Copy the block of data from the SteamDRMP.dll data.. var drmpOffsetData = new byte[1024]; Array.Copy(this.SteamDrmpData, drmpOffset, drmpOffsetData, 0, 1024); // Obtain the offsets from the file data.. var drmpOffsets = (this.Options.UseExperimentalFeatures) ? this.GetSteamDrmpOffsetsDynamic(drmpOffsetData) : this.GetSteamDrmpOffsets(drmpOffsetData); if (drmpOffsets.Count != 8) { return(false); } // Store the offsets.. this.SteamDrmpOffsets = drmpOffsets; return(true); }
/// <summary> /// Processing function called when a file is being unpacked. Allows plugins to check the file /// and see if it can handle the file for its intended purpose. /// </summary> /// <param name="file"></param> /// <returns></returns> public override bool CanProcessFile(string file) { try { // Load the file.. var f = new Pe32File(file); if (!f.Parse() || f.IsFile64Bit() || !f.HasSection(".bind")) { return(false); } // Obtain the bind section data.. var bind = f.GetSectionData(".bind"); // Attempt to locate the known v2.0 signature.. return(Pe32Helpers.FindPattern(bind, "53 51 52 56 57 55 8B EC 81 EC 00 10 00 00 BE") != -1); } catch { return(false); } }