diff --git a/SharpSploit/Execution/DynamicInvoke/Generic.cs b/SharpSploit/Execution/DynamicInvoke/Generic.cs
index 0ba7254..cae36e2 100644
--- a/SharpSploit/Execution/DynamicInvoke/Generic.cs
+++ b/SharpSploit/Execution/DynamicInvoke/Generic.cs
@@ -634,28 +634,19 @@ public static object CallMappedDLLModuleExport(PE.PE_META_DATA PEINFO, IntPtr Mo
///
/// Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll.
///
- /// Ruben Boonen (@FuzzySec)
+ /// Ruben Boonen (@FuzzySec) and Paul Laîné (@am0nsec)
/// The name of the function to search for (e.g. "NtAlertResumeThread").
/// IntPtr, Syscall stub
- public static IntPtr GetSyscallStub(string FunctionName)
- {
- // Verify process & architecture
- bool isWOW64 = Native.NtQueryInformationProcessWow64Information((IntPtr)(-1));
- if (IntPtr.Size == 4 && isWOW64)
- {
- throw new InvalidOperationException("Generating Syscall stubs is not supported for WOW64.");
- }
+ public static IntPtr GetSyscallStub(string FunctionName) {
// Find the path for ntdll by looking at the currently loaded module
- string NtdllPath = string.Empty;
- ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
- foreach (ProcessModule Mod in ProcModules)
- {
- if (Mod.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase))
- {
- NtdllPath = Mod.FileName;
+ ProcessModule NativeModule = null;
+ foreach (ProcessModule _ in Process.GetCurrentProcess().Modules) {
+ if (_.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase)) {
+ NativeModule = _;
}
}
+ string NtdllPath = NativeModule.FileName;
// Alloc module into memory for parsing
IntPtr pModule = Execute.ManualMap.Map.AllocateFileToMemory(NtdllPath);
@@ -678,24 +669,21 @@ public static IntPtr GetSyscallStub(string FunctionName)
UInt32 BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders);
// Write sections to memory
- foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections)
- {
+ foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections) {
// Calculate offsets
IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress);
IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData);
// Write data
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData);
- if (BytesWritten != ish.SizeOfRawData)
- {
+ if (BytesWritten != ish.SizeOfRawData) {
throw new InvalidOperationException("Failed to write to memory.");
}
}
// Get Ptr to function
IntPtr pFunc = GetExportAddress(pImage, FunctionName);
- if (pFunc == IntPtr.Zero)
- {
+ if (pFunc == IntPtr.Zero) {
throw new InvalidOperationException("Failed to resolve ntdll export.");
}
@@ -710,11 +698,33 @@ public static IntPtr GetSyscallStub(string FunctionName)
// Write call stub
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pCallStub, pFunc, 0x50);
- if (BytesWritten != 0x50)
- {
+ if (BytesWritten != 0x50) {
throw new InvalidOperationException("Failed to write to memory.");
}
+ // Verify process & architecture
+ bool isWOW64 = Native.NtQueryInformationProcessWow64Information((IntPtr)(-1));
+
+ // Create custom WOW64 stub
+ if (IntPtr.Size == 4 && isWOW64) {
+ IntPtr pNativeWow64Transition = GetExportAddress(NativeModule.BaseAddress, "Wow64Transition");
+ byte bRetValue = Marshal.ReadByte(pCallStub, 13);
+
+ // CALL DWORD PTR ntdll!Wow64SystemServiceCall
+ Marshal.WriteByte(pCallStub, 5, 0xff);
+ Marshal.WriteByte(pCallStub, 6, 0x15);
+ Marshal.WriteInt32(pCallStub, 7, pNativeWow64Transition.ToInt32());
+
+ // RET
+ Marshal.WriteByte(pCallStub, 11, 0xc2);
+ Marshal.WriteByte(pCallStub, 12, bRetValue);
+ Marshal.WriteByte(pCallStub, 13, 0x00);
+
+ // NOP for alignment
+ Marshal.WriteByte(pCallStub, 14, 0x90);
+ Marshal.WriteByte(pCallStub, 15, 0x90);
+ }
+
// Change call stub permissions
Native.NtProtectVirtualMemory((IntPtr)(-1), ref pCallStub, ref RegionSize, Execute.Win32.WinNT.PAGE_EXECUTE_READ);
@@ -727,4 +737,4 @@ public static IntPtr GetSyscallStub(string FunctionName)
return pCallStub;
}
}
-}
\ No newline at end of file
+}