/// <summary> /// Resolve host DLL for API Set DLL. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <returns>Dictionary, a combination of Key:APISetDLL and Val:HostDLL.</returns> public static Dictionary <string, string> GetApiSetMapping() { Data.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); UInt32 ApiSetMapOffset = IntPtr.Size == 4 ? (UInt32)0x38 : 0x68; // Create mapping dictionary Dictionary <string, string> ApiSetDict = new Dictionary <string, string>(); IntPtr pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + ApiSetMapOffset)); Data.PE.ApiSetNamespace Namespace = (Data.PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(Data.PE.ApiSetNamespace)); for (var i = 0; i < Namespace.Count; i++) { Data.PE.ApiSetNamespaceEntry SetEntry = new Data.PE.ApiSetNamespaceEntry(); SetEntry = (Data.PE.ApiSetNamespaceEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)Namespace.EntryOffset + (UInt64)(i * Marshal.SizeOf(SetEntry))), typeof(Data.PE.ApiSetNamespaceEntry)); string ApiSetEntryName = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.NameOffset), SetEntry.NameLength / 2) + ".dll"; Data.PE.ApiSetValueEntry SetValue = new Data.PE.ApiSetValueEntry(); SetValue = (Data.PE.ApiSetValueEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset), typeof(Data.PE.ApiSetValueEntry)); string ApiSetValue = string.Empty; if (SetValue.ValueCount != 0) { ApiSetValue = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetValue.ValueOffset), SetValue.ValueCount / 2); } // Add pair to dict ApiSetDict.Add(ApiSetEntryName, ApiSetValue); } // Return dict return(ApiSetDict); }
/// <summary> /// Helper for getting the base address of a module loaded by the current process. This base /// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for /// manual export parsing. This function parses the _PEB_LDR_DATA structure. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param> /// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns> public static IntPtr GetPebLdrModuleEntry(string DLLName) { // Get _PEB pointer Data.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); // Set function variables bool Is32Bit = false; UInt32 LdrDataOffset = 0; UInt32 InLoadOrderModuleListOffset = 0; if (IntPtr.Size == 4) { Is32Bit = true; LdrDataOffset = 0xc; InLoadOrderModuleListOffset = 0xC; } else { LdrDataOffset = 0x18; InLoadOrderModuleListOffset = 0x10; } // Get module InLoadOrderModuleList -> _LIST_ENTRY IntPtr PEB_LDR_DATA = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + LdrDataOffset)); IntPtr pInLoadOrderModuleList = (IntPtr)((UInt64)PEB_LDR_DATA + InLoadOrderModuleListOffset); Data.Native.LIST_ENTRY le = (Data.Native.LIST_ENTRY)Marshal.PtrToStructure(pInLoadOrderModuleList, typeof(Data.Native.LIST_ENTRY)); // Loop entries IntPtr flink = le.Flink; IntPtr hModule = IntPtr.Zero; Data.PE.LDR_DATA_TABLE_ENTRY dte = (Data.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(Data.PE.LDR_DATA_TABLE_ENTRY)); while (dte.InLoadOrderLinks.Flink != le.Blink) { // Match module name if (Marshal.PtrToStringUni(dte.FullDllName.Buffer).EndsWith(DLLName, StringComparison.OrdinalIgnoreCase)) { hModule = dte.DllBase; } // Move Ptr flink = dte.InLoadOrderLinks.Flink; dte = (Data.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(Data.PE.LDR_DATA_TABLE_ENTRY)); } return(hModule); }
/// <summary> /// Helper for getting the base address of a module loaded by the current process. This base /// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for /// manual export parsing. This function parses the _PEB_LDR_DATA structure. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> /// <param name="dllName">The name of the DLL (e.g. "ntdll.dll").</param> /// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns> public static IntPtr GetPebLdrModuleEntry(string dllName) { // Get _PEB pointer var pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); // Set function variables uint ldrDataOffset = 0; uint inLoadOrderModuleListOffset = 0; if (IntPtr.Size == 4) { ldrDataOffset = 0xc; inLoadOrderModuleListOffset = 0xC; } else { ldrDataOffset = 0x18; inLoadOrderModuleListOffset = 0x10; } // Get module InLoadOrderModuleList -> _LIST_ENTRY var PEB_LDR_DATA = Marshal.ReadIntPtr((IntPtr)((ulong)pbi.PebBaseAddress + ldrDataOffset)); var pInLoadOrderModuleList = (IntPtr)((ulong)PEB_LDR_DATA + inLoadOrderModuleListOffset); var le = (Data.Native.LIST_ENTRY)Marshal.PtrToStructure(pInLoadOrderModuleList, typeof(Data.Native.LIST_ENTRY)); // Loop entries var flink = le.Flink; var hModule = IntPtr.Zero; var dte = (Data.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(Data.PE.LDR_DATA_TABLE_ENTRY)); while (dte.InLoadOrderLinks.Flink != le.Blink) { // Match module name if (Marshal.PtrToStringUni(dte.FullDllName.Buffer).EndsWith(dllName, StringComparison.OrdinalIgnoreCase)) { hModule = dte.DllBase; } // Move Ptr flink = dte.InLoadOrderLinks.Flink; dte = (Data.PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(Data.PE.LDR_DATA_TABLE_ENTRY)); } return(hModule); }
/// <summary> /// Resolve host DLL for API Set DLL. /// </summary> /// <author>Ruben Boonen (@FuzzySec), The Wover (@TheRealWover)</author> /// <returns>Dictionary, a combination of Key:APISetDLL and Val:HostDLL.</returns> public static Dictionary <string, string> GetApiSetMapping() { Data.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); UInt32 ApiSetMapOffset = IntPtr.Size == 4 ? (UInt32)0x38 : 0x68; // Create mapping dictionary Dictionary <string, string> ApiSetDict = new Dictionary <string, string>(); IntPtr pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + ApiSetMapOffset)); Data.PE.ApiSetNamespace Namespace = (Data.PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(Data.PE.ApiSetNamespace)); for (var i = 0; i < Namespace.Count; i++) { Data.PE.ApiSetNamespaceEntry SetEntry = new Data.PE.ApiSetNamespaceEntry(); IntPtr pSetEntry = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)Namespace.EntryOffset + (UInt64)(i * Marshal.SizeOf(SetEntry))); SetEntry = (Data.PE.ApiSetNamespaceEntry)Marshal.PtrToStructure(pSetEntry, typeof(Data.PE.ApiSetNamespaceEntry)); string ApiSetEntryName = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.NameOffset), SetEntry.NameLength / 2); string ApiSetEntryKey = ApiSetEntryName.Substring(0, ApiSetEntryName.Length - 2) + ".dll"; // Remove the patch number and add .dll Data.PE.ApiSetValueEntry SetValue = new Data.PE.ApiSetValueEntry(); IntPtr pSetValue = IntPtr.Zero; // If there is only one host, then use it if (SetEntry.ValueLength == 1) { pSetValue = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset); } else if (SetEntry.ValueLength > 1) { // Loop through the hosts until we find one that is different from the key, if available for (var j = 0; j < SetEntry.ValueLength; j++) { IntPtr host = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset + (UInt64)Marshal.SizeOf(SetValue) * (UInt64)j); if (Marshal.PtrToStringUni(host) != ApiSetEntryName) { pSetValue = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset + (UInt64)Marshal.SizeOf(SetValue) * (UInt64)j); } } // If there is not one different from the key, then just use the key and hope that works if (pSetValue == IntPtr.Zero) { pSetValue = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset); } } //Get the host DLL's name from the entry SetValue = (Data.PE.ApiSetValueEntry)Marshal.PtrToStructure(pSetValue, typeof(Data.PE.ApiSetValueEntry)); string ApiSetValue = string.Empty; if (SetValue.ValueCount != 0) { IntPtr pValue = (IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetValue.ValueOffset); ApiSetValue = Marshal.PtrToStringUni(pValue, SetValue.ValueCount / 2); } // Add pair to dict ApiSetDict.Add(ApiSetEntryKey, ApiSetValue); } // Return dict return(ApiSetDict); }
/// <summary> /// Resolve host DLL for API Set DLL. /// </summary> /// <author>Ruben Boonen (@FuzzySec), The Wover (@TheRealWover)</author> /// <returns>Dictionary, a combination of Key:APISetDLL and Val:HostDLL.</returns> public static Dictionary <string, string> GetApiSetMapping() { var pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1)); var apiSetMapOffset = IntPtr.Size == 4 ? (uint)0x38 : 0x68; var apiSetDict = new Dictionary <string, string>(); var pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((ulong)pbi.PebBaseAddress + apiSetMapOffset)); var apiSetNamespace = (Data.PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(Data.PE.ApiSetNamespace)); for (var i = 0; i < apiSetNamespace.Count; i++) { var setEntry = new Data.PE.ApiSetNamespaceEntry(); var pSetEntry = (IntPtr)((ulong)pApiSetNamespace + (ulong)apiSetNamespace.EntryOffset + (ulong)(i * Marshal.SizeOf(setEntry))); setEntry = (Data.PE.ApiSetNamespaceEntry)Marshal.PtrToStructure(pSetEntry, typeof(Data.PE.ApiSetNamespaceEntry)); var apiSetEntryName = Marshal.PtrToStringUni((IntPtr)((ulong)pApiSetNamespace + (ulong)setEntry.NameOffset), setEntry.NameLength / 2); var apiSetEntryKey = apiSetEntryName.Substring(0, apiSetEntryName.Length - 2) + ".dll"; // Remove the patch number and add .dll var valueEntry = new Data.PE.ApiSetValueEntry(); var pSetValue = IntPtr.Zero; switch (setEntry.ValueLength) { case 1: pSetValue = (IntPtr)((ulong)pApiSetNamespace + (ulong)setEntry.ValueOffset); break; case > 1: { for (var j = 0; j < setEntry.ValueLength; j++) { var host = (IntPtr)((ulong)pApiSetNamespace + (ulong)setEntry.ValueOffset + (ulong)Marshal.SizeOf(valueEntry) * (ulong)j); if (Marshal.PtrToStringUni(host) != apiSetEntryName) { pSetValue = (IntPtr)((ulong)pApiSetNamespace + (ulong)setEntry.ValueOffset + (ulong)Marshal.SizeOf(valueEntry) * (ulong)j); } } if (pSetValue == IntPtr.Zero) { pSetValue = (IntPtr)((ulong)pApiSetNamespace + (ulong)setEntry.ValueOffset); } break; } } valueEntry = (Data.PE.ApiSetValueEntry)Marshal.PtrToStructure(pSetValue, typeof(Data.PE.ApiSetValueEntry)); var apiSetValue = string.Empty; if (valueEntry.ValueCount != 0) { var pValue = (IntPtr)((ulong)pApiSetNamespace + (ulong)valueEntry.ValueOffset); apiSetValue = Marshal.PtrToStringUni(pValue, valueEntry.ValueCount / 2); } apiSetDict.Add(apiSetEntryKey, apiSetValue); } return(apiSetDict); }