internal static byte[] CreateThreadIntercept32(PointerEx jumpTo, PointerEx originalIP) { List <byte> data = new List <byte> { // pusha 0x60, // pushf 0x9c, // mov eax, jumpTo 0xb8 }; data.AddRange(BitConverter.GetBytes((int)jumpTo)); // call eax data.AddRange(new byte[] { 0xff, 0xd0 }); // popf data.Add(0x9d); // popa data.Add(0x61); // push originalIP data.Add(0x68); data.AddRange(BitConverter.GetBytes((int)originalIP)); // ret data.Add(0xC3); return(data.ToArray()); }
public PointerEx this[PointerEx offset] { get { return(offset + BaseAddress); } }
public ProcessModuleExportEx(string name, PointerEx absoluteAddress, int ordinal, string forwarderString) { Ordinal = ordinal; AbsoluteAddress = absoluteAddress; Name = name; Forwarder = forwarderString; }
public static ProcessModuleEx FromMappedModule(PointerEx moduleHandle, byte[] moduleData) { ProcessModuleEx pmx = new ProcessModuleEx(moduleHandle, null); pmx.CacheExports(moduleData); pmx.IsManualMapped = true; return(pmx); }
public static byte[] CreateRemoteCall(PointerEx jumpLocation, PointerEx[] args, int pointerSize, PointerEx raxStorAddress, PointerEx threadStateAddress, byte xmmMask_64 = 0, ExXMMReturnType xmmReturnType = ExXMMReturnType.XMMR_NONE) { if (pointerSize == 8) { return(CreateRemoteCall64(jumpLocation, args, raxStorAddress, threadStateAddress, xmmMask_64, xmmReturnType)); } return(CreateRemoteCall32(jumpLocation, args, raxStorAddress, threadStateAddress)); }
private void MMLoadDependencies(PEImage sModule, PointerEx hModule) { var activationContext = new PEActivationContext(sModule.Resources.GetManifest(), HostProcess); foreach (var dependency in sModule.Imports.GetImportDescriptors()) { //var dependencyFilePath = ResolveFilePath(activationContext, _processContext.ResolveModuleName(dependency.Name)); } }
/// <summary> /// Converts a struct to a byte array /// </summary> /// <typeparam name="T"></typeparam> /// <param name="s"></param> /// <returns></returns> public static byte[] ToByteArray <T>(this T s) where T : struct { PointerEx size = Marshal.SizeOf(s); byte[] data = new byte[size]; PointerEx dwStruct = Marshal.AllocHGlobal((int)size); Marshal.StructureToPtr(s, dwStruct, true); Marshal.Copy(dwStruct, data, 0, size); Marshal.FreeHGlobal(dwStruct); return(data); }
private static byte[] CreateRemoteCall32(PointerEx jumpLocation, PointerEx[] args, PointerEx eaxStorAddress, PointerEx threadStateAddress) { List <byte> data = new List <byte>(); foreach (var arg in args.Reverse()) { if (arg <= byte.MaxValue) { // push byte data.AddRange(new byte[] { 0x6A, arg }); } else { // push int32 data.Add(0x68); data.AddRange(BitConverter.GetBytes((int)arg)); } } // mov eax, jumpLoc data.Add(0xB8); data.AddRange(BitConverter.GetBytes((int)jumpLocation)); // call eax data.AddRange(new byte[] { 0xFF, 0xD0 }); if (eaxStorAddress) { // mov eaxStorAddress, eax data.Add(0xA3); data.AddRange(BitConverter.GetBytes((int)eaxStorAddress)); } // mov eax, threadStateAddress data.Add(0xB8); data.AddRange(BitConverter.GetBytes((int)threadStateAddress)); // change thread state to finished // mov DWORD PTR [eax], 0x1 data.AddRange(new byte[] { 0xC7, 0x00, 0x01, 0x00, 0x00, 0x00 }); // xor eax, eax data.AddRange(new byte[] { 0x33, 0xC0 }); // ret data.Add(0xC3); return(data.ToArray()); }
public PointerEx Size() { PointerEx n_size = InternalDataOffsetEnd; n_size = n_size.Align(ARG_ALIGN); foreach (var arg in Arguments) { if (!arg.IsReferenceType) { continue; } n_size += arg.Data.Length; n_size = n_size.Align(ARG_ALIGN); } return(n_size); }
public byte[] Build(PointerEx baseAddress) { byte[] data = new byte[Size()]; PointerEx index = InternalDataOffsetEnd; index = index.Align(ARG_ALIGN); foreach (var arg in Arguments) { if (!arg.IsReferenceType) { continue; } arg.Handle = index + baseAddress; arg.Data.CopyTo(data, index); index += arg.Data.Length; index = index.Align(ARG_ALIGN); } return(data); }
/// <summary> /// Manually map module into remote process. /// </summary> /// <author>Ruben Boonen (@FuzzySec)</author> (modified for external ProcessEx) /// <param name="localModuleHandle">Pointer to the module base.</param> /// <returns>PE_MANUAL_MAP object</returns> private PE_MANUAL_MAP MapModuleToMemory(PointerEx localModuleHandle, byte[] moduleRaw) { #if DEBUG DLog($"Attempting to map module of size {moduleRaw.Length}"); #endif // Fetch PE meta data PE_META_DATA PEINFO = GetPeMetaData(localModuleHandle); // Check module matches the process architecture if ((PEINFO.Is32Bit && IntPtr.Size == 8) || (!PEINFO.Is32Bit && IntPtr.Size == 4)) { Marshal.FreeHGlobal(localModuleHandle); throw new InvalidOperationException(DSTR(DSTR_MOD_ARCHITECTURE_WRONG)); } // Alloc PE image memory -> RW IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage; IntPtr remoteModuleHandle = QuickAlloc(RegionSize); #if DEBUG DLog($"Module memory allocated at 0x{remoteModuleHandle.ToInt64():X16}"); #endif return(__MapModuleToMemory(localModuleHandle, remoteModuleHandle, moduleRaw, PEINFO)); }
public bool TryMapModule(out PointerEx hModule) { var sModule = new PEImage(RawDLL); hModule = NativeStealth.VirtualAllocEx(HostProcess.Handle, 0, (uint)sModule.Headers.PEHeader.SizeOfImage, Native.AllocationType.Commit | Native.AllocationType.Reserve, Native.MemoryProtection.ReadOnly); if (!hModule) { throw new Exception("Unable to allocate enough memory to map the module"); } try { MMLoadDependencies(sModule, hModule); } catch { if (HostProcess.Handle) { ProcessEx.VirtualFreeEx(HostProcess.Handle, hModule, (uint)sModule.Headers.PEHeader.SizeOfImage, (int)FreeType.Release); } throw; } ModuleHandle = hModule; return(true); }
// credit: https://github.com/erfg12/memory.dll/blob/master/Memory/memory.cs public Task <IEnumerable <PointerEx> > Search(string query, PointerEx start, PointerEx end, MemorySearchFlags flags) { return(Task.Run(() => { var Results = new List <SearcherResult>(); string[] patterns = query.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); byte[] finalPattern = new byte[patterns.Length]; byte[] mask = new byte[patterns.Length]; for (int i = 0; i < patterns.Length; i++) { string s = patterns[i]; if (s == "?") { mask[i] = 0; } else if (s.Length < 2) { if (s.HexByte(out byte b)) { finalPattern[i] = b; } mask[i] = 0xFF; } else { mask[i] = (byte)((s[0].IsHex() ? 0xF0 : 0) + (s[1].IsHex() ? 0x0F : 0)); if ((mask[i] & 0xF0) > 0) { finalPattern[i] += (byte)(s[0].HexByte() * 0x10); } if ((mask[i] & 0xF) > 0) { finalPattern[i] += s[1].HexByte(); } } } var sysInfo = new ProcessEx.SYSTEM_INFO(); ProcessEx.GetSystemInfo(out sysInfo); PointerEx proc_min_address = sysInfo.lpMinimumApplicationAddress; PointerEx proc_max_address = sysInfo.lpMaximumApplicationAddress; if (start < proc_min_address) { start = proc_min_address; } if (end > proc_max_address) { end = proc_max_address; } PointerEx cBase = start.Clone(); var memInfo = new ProcessEx.MEMORY_BASIC_INFORMATION(); while (ProcessEx.VirtualQueryEx(Proc.Handle, cBase, out memInfo, (uint)Marshal.SizeOf(memInfo)) && cBase < end && cBase + memInfo.RegionSize > cBase) { bool isValid = memInfo.State == ProcessEx.MEM_COMMIT; isValid &= memInfo.BaseAddress < proc_max_address; isValid &= ((memInfo.Protect & Native.PAGE_GUARD) == 0); isValid &= ((memInfo.Protect & Native.PAGE_NOACCESS) == 0); isValid &= (memInfo.Type == ProcessEx.MEM_PRIVATE) || (memInfo.Type == ProcessEx.MEM_IMAGE); if (isValid) { bool isReadable = (memInfo.Protect & Native.PAGE_READONLY) > 0; bool isWritable = ((memInfo.Protect & Native.PAGE_READWRITE) > 0) || ((memInfo.Protect & Native.PAGE_WRITECOPY) > 0) || ((memInfo.Protect & Native.PAGE_EXECUTE_READWRITE) > 0) || ((memInfo.Protect & Native.PAGE_EXECUTE_WRITECOPY) > 0); bool isExecutable = ((memInfo.Protect & Native.PAGE_EXECUTE) > 0) || ((memInfo.Protect & Native.PAGE_EXECUTE_READ) > 0) || ((memInfo.Protect & Native.PAGE_EXECUTE_READWRITE) > 0) || ((memInfo.Protect & Native.PAGE_EXECUTE_WRITECOPY) > 0); isReadable &= ((byte)flags & (byte)MemorySearchFlags.Read) > 0; isWritable &= ((byte)flags & (byte)MemorySearchFlags.Write) > 0; isExecutable &= ((byte)flags & (byte)MemorySearchFlags.Execute) > 0; isValid &= isReadable || isWritable || isExecutable; } cBase = memInfo.BaseAddress + memInfo.RegionSize; if (!isValid) { continue; } SearcherResult result = new SearcherResult { BaseAddress = cBase - memInfo.RegionSize, RegionSize = memInfo.RegionSize, RegionBase = memInfo.BaseAddress }; if (Results.Count > 0) { var previousRegion = Results[Results.Count - 1]; if ((previousRegion.RegionBase + previousRegion.RegionSize) == memInfo.BaseAddress) { Results[Results.Count - 1] = new SearcherResult { BaseAddress = previousRegion.BaseAddress, RegionBase = previousRegion.RegionBase, RegionSize = previousRegion.RegionSize + memInfo.RegionSize }; continue; } } Results.Add(result); } // end while ConcurrentBag <PointerEx> bagResult = new ConcurrentBag <PointerEx>(); Parallel.ForEach(Results, (item, parallelLoopState, index) => { PointerEx[] compareResults = CompareScan(item, finalPattern, mask); foreach (PointerEx result in compareResults) { bagResult.Add(result); } }); return bagResult.ToList().OrderBy(c => c).AsEnumerable(); })); }
public static PointerEx Align(this PointerEx value, uint alignment) => (value + (alignment - 1)) & ~(alignment - 1);
public static PointerEx Subtract(this PointerEx i, PointerEx offset) { return(i.IntPtr.Subtract(offset)); }
public static PointerEx Add(this PointerEx i, PointerEx offset) { return(i.IntPtr.Add(offset)); }
public static extern int NtCreateThreadEx(out SafeWaitHandle threadHandle, AccessMask accessMask, PointerEx objectAttributes, PointerEx processHandle, PointerEx startAddress, PointerEx argument, ThreadCreationFlags flags, PointerEx zeroBits, PointerEx stackSize, PointerEx maximumStackSize, IntPtr attributeList);
static EnvironmentEx() { if (Environment.Is64BitProcess) { APISetMapAddress = Marshal.PtrToStructure <Peb64>(RtlGetCurrentPeb()).APISetMap; } else { APISetMapAddress = Marshal.PtrToStructure <Peb32>(RtlGetCurrentPeb()).APISetMap; } #region DSTRINGS #if DEBUG DSTR_MODULE_EXPORT_NOT_FOUND = CreateDebugString("Module '{0}' does not contain export '{1}'"); DSTR_OS_VERSION_TOO_OLD = CreateDebugString("OS Major Version must be >= 10"); DSTR_MODULE_NAME_INVALID = CreateDebugString("Failed to read imported DLL name."); DSTR_MODULE_FILE_NOT_FOUND = CreateDebugString("{0}, unable to find the specified file."); DSTR_DINVOKE_MAIN_FAILED = CreateDebugString("Failed to call DllMain -> DLL_PROCESS_ATTACH"); DSTR_DINVOKE_MOD_CANNOT_BE_NULL = CreateDebugString("modulePath cannot be null."); DSTR_MOD_ARCHITECTURE_WRONG = CreateDebugString("The module architecture does not match the process architecture."); DSTR_MOD_EXPORTS_BAD = CreateDebugString("Failed to parse module exports."); DSTR_EXPORT_NOT_FOUND = CreateDebugString("{0}, export not found."); DSTR_FAILED_MEMORY_WRITE = CreateDebugString("Failed to write to memory."); DSTR_MEM_ACCESS_VIOLATION = CreateDebugString("Memory access violation."); DSTR_API_DLL_UNRESOLVED = CreateDebugString("api dll was not resolved ({0})"); DSTR_UNK_SEC_FLAG = CreateDebugString("Unknown section flag, {0}"); DSTR_RAXSTOR_MISSING = CreateDebugString("Unable to execute a 64 bit function without RAXStor"); DSTR_ACCESS_DENIED = CreateDebugString("Access is denied."); DSTR_ALREADY_COMMITTED = CreateDebugString("The specified address range is already committed."); DSTR_LOW_ON_VMEM = CreateDebugString("Your system is low on virtual memory."); DSTR_CONFLICTING_ADDRESS = CreateDebugString("The specified address range conflicts with the address space."); DSTR_INSUFFICIENT_RESOURCES = CreateDebugString("Insufficient system resources exist to complete the API call."); DSTR_INVALID_HANDLE = CreateDebugString("Invalid handle"); DSTR_INVALID_PAGE_PROTECT = CreateDebugString("The specified page protection was not valid."); DSTR_OBJECT_TYPE_MISMATCH = CreateDebugString("Object type mismatch"); DSTR_PROC_EXITING = CreateDebugString("An attempt was made to duplicate an object handle into or out of an exiting process."); DSTR_PROC_ADDRESS_LOOKUP_FAILED = CreateDebugString("Failed get procedure address, {0}"); DSTR_INVALID_PROCINFOCLASS = CreateDebugString("Invalid ProcessInfoClass {0}"); DSTR_FAILED_MEMPROTECT = CreateDebugString("Failed to change memory protection, {0}"); DSTR_BUFFER_TOO_SMALL = CreateDebugString("Destination buffer size is too small"); DSTR_PTR_CAST_FAIL = CreateDebugString("Cannot cast data of length {0} to a pointer of size {1}"); DSTR_TARG_PROC_NULL = CreateDebugString("Target process cannot be null"); DSTR_READ_MISSING_HANDLE = CreateDebugString("Tried to read from a memory region when a handle to the desired process doesn't exist"); DSTR_INVALID_VALUETYPE = CreateDebugString("Type {0} is not a valid value type"); DSTR_WRITE_MISSING_HANDLE = CreateDebugString("Tried to write to a memory region when a handle to the desired process doesn't exist"); DSTR_FAILED_READFROM = CreateDebugString("Failed to read data of size {0} from address 0x{1}"); DSTR_FAILED_WRITETO = CreateDebugString("Failed to write {0} bytes to region 0x{1}"); DSTR_INJECT_DEAD_PROC = CreateDebugString("Cannot inject a dll to a process which has exited"); DSTR_INJECT_EMPTY_DLL = CreateDebugString("DSTR_INJECT_EMPTY_DLL"); DSTR_FAILED_LOAD_MODULE = CreateDebugString("Failed to load an essential module at '{0}'"); DSTR_CAST_SERIALIZE_FAILED = CreateDebugString("Cannot cast type [{0}] to a serializable type for RPC returns"); DSTR_RPC_INITIALIZED = CreateDebugString("Cannot invoke rpc of type {0} because the rpc type has not been initialized."); DSTR_PROC_EXITED = CreateDebugString("Process exited unexpectedly..."); DSTR_FIND_THREAD_HIJACK = CreateDebugString("Unable to find a thread which can be hijacked."); DSTR_OPEN_THREAD_FAILED = CreateDebugString("Unable to open target thread for RPC..."); DSTR_THREAD_CTX_FAILED = CreateDebugString("Unable to get a thread context for the target process RPC."); DSTR_RPC_TIMEOUT = CreateDebugString("Function call timed out"); DSTR_ALLOC_NO_HANDLE = CreateDebugString("Tried to allocate a memory region when a handle to the desired process doesn't exist"); DSTR_THREAD_NO_HANDLE = CreateDebugString("Tried to create a thread in a process which has no open handle!"); DSTR_CALLTYPE_NOT_IMPLEMENTED = CreateDebugString("Calltype {0} not implemented"); DSTR_SERIALIZE_TYPE_INVALID = CreateDebugString("Cannot cast type [{0}] to a serializable type for RPC. If this was an array, convert it to a byte array first."); DSTR_UNHANDLED_ARG_RPC = CreateDebugString("Unhandled argument type for serialization: {0}"); #endif #endregion }
internal ProcessModuleEx(PointerEx baseAddress, string modulePath) { __baseaddress = baseAddress; __modulepath = modulePath; }
private static byte[] CreateRemoteCall64(PointerEx jumpLocation, PointerEx[] args, PointerEx raxStorAddress, PointerEx threadStateAddress, byte xmmMask, ExXMMReturnType xmmReturnType) { if (!raxStorAddress) { throw new Exception(DSTR(DSTR_RAXSTOR_MISSING)); } List <byte> data = new List <byte>(); // movabs rax, raxStorAddress data.AddRange(new byte[] { 0x48, 0xb8 }); data.AddRange(BitConverter.GetBytes((long)raxStorAddress)); // mov QWORD PTR [rax], rsp // mov rax, -16 // and rsp, rax // sub rsp, 32 data.AddRange(new byte[] { 0x48, 0x89, 0x20, 0x48, 0xC7, 0xC0, 0xF0, 0xFF, 0xFF, 0xFF, 0x48, 0x21, 0xC4, 0x48, 0x83, 0xEC, 0x20 }); for (int i = args.Length - 1; i > -1; i--) { var arg = args[i]; if (i < 4 && (PointerEx)(xmmMask & (1 << i))) { bool is64xmm = (PointerEx)(xmmMask & (1 << i + 4)); // mov rax, arg data.AddRange(new byte[] { 0x48, 0xb8 }); data.AddRange(BitConverter.GetBytes((long)arg)); if (is64xmm) { // movlpd xmm<?>, QWORD PTR [rax] data.AddRange(new byte[] { 0x66, 0x0f, 0x12 }); data.Add((byte)(i * 8)); } else { // movss xmm<?>, DWORD PTR [rax] data.AddRange(new byte[] { 0xf3, 0x0f, 0x10 }); data.Add((byte)(i * 8)); } continue; } switch (i) { case ARG_RCX: { if (!arg) { // xor ecx, ecx data.AddRange(new byte[] { 0x31, 0xC9 }); break; } if (arg <= (long)uint.MaxValue) { // mov ecx, arg data.Add(0xB9); data.AddRange(BitConverter.GetBytes((int)arg)); break; } // mov rcx, arg data.AddRange(new byte[] { 0x48, 0xB9 }); data.AddRange(BitConverter.GetBytes((long)arg)); } break; case ARG_RDX: { if (!arg) { // xor edx, edx data.AddRange(new byte[] { 0x31, 0xD2 }); break; } if (arg <= (long)uint.MaxValue) { // mov edx, arg data.Add(0xBA); data.AddRange(BitConverter.GetBytes((int)arg)); break; } // mov rdx, arg data.AddRange(new byte[] { 0x48, 0xBA }); data.AddRange(BitConverter.GetBytes((long)arg)); } break; case ARG_R8: { if (!arg) { // xor r8d, r8d data.AddRange(new byte[] { 0x45, 0x31, 0xC0 }); break; } if (arg <= (long)uint.MaxValue) { // mov r8d, arg data.AddRange(new byte[] { 0x41, 0xB8 }); data.AddRange(BitConverter.GetBytes((int)arg)); break; } // mov r8, arg data.AddRange(new byte[] { 0x49, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)arg)); } break; case ARG_R9: { if (!arg) { // xor r9d, r8d data.AddRange(new byte[] { 0x45, 0x31, 0xC9 }); break; } if (arg <= (long)uint.MaxValue) { // mov r9d, arg data.AddRange(new byte[] { 0x41, 0xB9 }); data.AddRange(BitConverter.GetBytes((int)arg)); break; } // mov r9, arg data.AddRange(new byte[] { 0x49, 0xB9 }); data.AddRange(BitConverter.GetBytes((long)arg)); } break; default: { if (!arg) { // push 0 data.AddRange(new byte[] { 0x6a, 0x00 }); break; } // mov rax, arg data.AddRange(new byte[] { 0x48, 0xb8 }); data.AddRange(BitConverter.GetBytes((long)arg)); // push rax data.Add(0x50); } break; } } // sub rsp, 0x20 for the shadow store data.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x20 }); // mov rax, jumploc data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)jumpLocation)); // call rax data.AddRange(new byte[] { 0xFF, 0xD0 }); // add rsp, 0x20 for removing shadow store data.AddRange(new byte[] { 0x48, 0x83, 0xC4, 0x20 }); // movabs rbx, raxStorAddress data.AddRange(new byte[] { 0x48, 0xBB }); data.AddRange(BitConverter.GetBytes((long)raxStorAddress)); // mov rsp, QWORD PTR[rbx] data.AddRange(new byte[] { 0x48, 0x8B, 0x23 }); if (xmmReturnType == ExXMMReturnType.XMMR_NONE) { // mov ReturnAddress, rax data.AddRange(new byte[] { 0x48, 0xA3 }); data.AddRange(BitConverter.GetBytes((long)raxStorAddress)); } else { // mov rax, ReturnAddress data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)raxStorAddress)); if (xmmReturnType == ExXMMReturnType.XMMR_SINGLE) { // movss DWORD PTR [rax], xmm0 data.AddRange(new byte[] { 0xF3, 0x0F, 0x11, 0x00 }); } else { // movlpd QWORD PTR [rax],xmm0 data.AddRange(new byte[] { 0x66, 0x0F, 0x13, 0x00 }); } } // mov rax, threadStateAddress data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)threadStateAddress)); // change thread state to finished // mov QWORD PTR [rax], 0x1 data.AddRange(new byte[] { 0x48, 0xC7, 0x00, 0x01, 0x00, 0x00, 0x00 }); // xor rax, rax data.AddRange(new byte[] { 0x31, 0xC0 }); // ret data.Add(0xC3); return(data.ToArray()); }
internal static byte[] CreateThreadIntercept64(PointerEx jumpTo, PointerEx originalIP, PointerEx xmmSpace) { List <byte> data = new List <byte>(); // pushf TWICE // the reason is because we need padding space behind the saved flags so that we can place our fake return pointer back there data.AddRange(new byte[] { 0x9C, 0x9C }); // push all the standard registers data.AddRange(new byte[] { 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57 }); // mov rax, xmmSpace data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)xmmSpace)); // save all the xmm registers to xmmSpace data.AddRange(new byte[] { 0x66, 0x0F, 0x29, 0x00, 0x66, 0x0F, 0x29, 0x48, 0x10, 0x66, 0x0F, 0x29, 0x50, 0x20, 0x66, 0x0F, 0x29, 0x58, 0x30, 0x66, 0x0F, 0x29, 0x60, 0x40, 0x66, 0x0F, 0x29, 0x68, 0x50, 0x66, 0x0F, 0x29, 0x70, 0x60, 0x66, 0x0F, 0x29, 0x78, 0x70, 0x66, 0x44, 0x0F, 0x29, 0x80, 0x80, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0x88, 0x90, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0x98, 0xB0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0xA0, 0xC0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0xA8, 0xD0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0xB0, 0xE0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x29, 0xB8, 0xF0, 0x00, 0x00, 0x00 }); // mov rax, jumpTo data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)jumpTo)); // call rax data.AddRange(new byte[] { 0xFF, 0xD0 }); // mov rax, xmmSpace data.AddRange(new byte[] { 0x48, 0xB8 }); data.AddRange(BitConverter.GetBytes((long)xmmSpace)); // load all the xmm registers from xmmSpace data.AddRange(new byte[] { 0x66, 0x0F, 0x28, 0x00, 0x66, 0x0F, 0x28, 0x48, 0x10, 0x66, 0x0F, 0x28, 0x50, 0x20, 0x66, 0x0F, 0x28, 0x58, 0x30, 0x66, 0x0F, 0x28, 0x60, 0x40, 0x66, 0x0F, 0x28, 0x68, 0x50, 0x66, 0x0F, 0x28, 0x70, 0x60, 0x66, 0x0F, 0x28, 0x78, 0x70, 0x66, 0x44, 0x0F, 0x28, 0x80, 0x80, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0x88, 0x90, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0x90, 0xA0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0x98, 0xB0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0xA0, 0xC0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0xA8, 0xD0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0xB0, 0xE0, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x28, 0xB8, 0xF0, 0x00, 0x00, 0x00 }); // pop all the standard registers data.AddRange(new byte[] { 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5F, 0x5E, 0x5D, 0x5C, 0x5B, 0x5A, 0x59, 0x58 }); // sub rsp, 0x8 // data.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x08 }); // no longer need to move rsp since we reserve space by flags push // mov DWORD PTR [rsp+8], originalIP_l data.AddRange(new byte[] { 0xC7, 0x44, 0x24, 0x08 }); data.AddRange(BitConverter.GetBytes((int)originalIP)); // mov DWORD PTR [rsp+0xC], originalIP_h data.AddRange(new byte[] { 0xC7, 0x44, 0x24, 0x0C }); data.AddRange(BitConverter.GetBytes((int)((long)originalIP >> 32))); // popf here, so flags are 100% correct data.Add(0x9D); // ret data.Add(0xC3); return(data.ToArray()); }