private static byte[] AssembleShellcode(CallDescriptor callDescriptor, IntPtr completionFlagBuffer) { var shellcode = new List <byte>(); if (callDescriptor.IsWow64Call) { // pushf shellcode.Add(0x9C); // pusha shellcode.Add(0x60); // Assemble the function parameters if (callDescriptor.CallingConvention == CallingConvention.FastCall) { ParameterAssembler.AssembleFastCallParameters(callDescriptor, ref shellcode); } else { ParameterAssembler.AssembleStdCallParameters(callDescriptor, ref shellcode); } // mov eax, functionAddress shellcode.Add(0xB8); shellcode.AddRange(BitConverter.GetBytes((int)callDescriptor.FunctionAddress)); // call eax shellcode.AddRange(new byte[] { 0xFF, 0xD0 }); if (callDescriptor.ReturnAddress != IntPtr.Zero) { // mov [returnAddress], eax shellcode.Add(0xA3); shellcode.AddRange(BitConverter.GetBytes((int)callDescriptor.ReturnAddress)); } // mov BYTE PTR [completionFlagBuffer], 0x01 shellcode.AddRange(new byte[] { 0xC6, 0x05 }); shellcode.AddRange(BitConverter.GetBytes((int)completionFlagBuffer)); shellcode.Add(0x01); // popa shellcode.Add(0x61); // popf shellcode.Add(0x9D); // ret shellcode.Add(0xC3); } else { // pushf shellcode.Add(0x9C); // push rax shellcode.Add(0x50); // push rbx shellcode.Add(0x53); // push rcx shellcode.Add(0x51); // push rdx shellcode.Add(0x52); // push r8 shellcode.AddRange(new byte[] { 0x41, 0x50 }); // push r9 shellcode.AddRange(new byte[] { 0x41, 0x51 }); // push r10 shellcode.AddRange(new byte[] { 0x41, 0x52 }); // push r11 shellcode.AddRange(new byte[] { 0x41, 0x53 }); // Assemble the function parameters ParameterAssembler.AssembleFastCallParameters(callDescriptor, ref shellcode); // mov rax, functionAddress shellcode.AddRange(new byte[] { 0x48, 0xB8 }); shellcode.AddRange(BitConverter.GetBytes((long)callDescriptor.FunctionAddress)); // sub rsp, 0x28 shellcode.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x28 }); // call rax shellcode.AddRange(new byte[] { 0xFF, 0xD0 }); // add rsp, 0x28 shellcode.AddRange(new byte[] { 0x48, 0x83, 0xC4, 0x28 }); if (callDescriptor.ReturnAddress != IntPtr.Zero) { // mov [returnAddress], rax shellcode.AddRange(new byte[] { 0x48, 0xA3 }); shellcode.AddRange(BitConverter.GetBytes((long)callDescriptor.ReturnAddress)); } // mov rax, completionFlagBuffer shellcode.AddRange(new byte[] { 0x48, 0xB8 }); shellcode.AddRange(BitConverter.GetBytes((long)completionFlagBuffer)); // mov BYTE PTR [rax], 0x01 shellcode.AddRange(new byte[] { 0xC6, 0x00, 0x01 }); // pop r11 shellcode.AddRange(new byte[] { 0x41, 0x5B }); // pop r10 shellcode.AddRange(new byte[] { 0x41, 0x5A }); // pop r9 shellcode.AddRange(new byte[] { 0x41, 0x59 }); // pop r8 shellcode.AddRange(new byte[] { 0x41, 0x58 }); // pop rdx shellcode.Add(0x5A); // pop rcx shellcode.Add(0x59); // pop rbx shellcode.Add(0x5B); // pop rax shellcode.Add(0x58); // popf shellcode.Add(0x9D); // ret shellcode.Add(0xC3); } return(shellcode.ToArray()); }
private static byte[] AssembleShellcode(CallDescriptor callDescriptor) { var shellcode = new List <byte>(); if (callDescriptor.IsWow64Call) { // Assemble the function parameters if (callDescriptor.CallingConvention == CallingConvention.FastCall) { ParameterAssembler.AssembleFastCallParameters(callDescriptor, ref shellcode); } else { ParameterAssembler.AssembleStdCallParameters(callDescriptor, ref shellcode); } // mov eax, functionAddress shellcode.Add(0xB8); shellcode.AddRange(BitConverter.GetBytes((int)callDescriptor.FunctionAddress)); // call eax shellcode.AddRange(new byte[] { 0xFF, 0xD0 }); if (callDescriptor.ReturnAddress != IntPtr.Zero) { // mov [returnAddress], eax shellcode.Add(0xA3); shellcode.AddRange(BitConverter.GetBytes((int)callDescriptor.ReturnAddress)); } // xor eax, eax shellcode.AddRange(new byte[] { 0x33, 0xC0 }); // ret shellcode.Add(0xC3); } else { // Assemble the function parameters ParameterAssembler.AssembleFastCallParameters(callDescriptor, ref shellcode); // mov rax, functionAddress shellcode.AddRange(new byte[] { 0x48, 0xB8 }); shellcode.AddRange(BitConverter.GetBytes((long)callDescriptor.FunctionAddress)); // sub rsp, 0x28 shellcode.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x28 }); // call rax shellcode.AddRange(new byte[] { 0xFF, 0xD0 }); // add rsp, 0x28 shellcode.AddRange(new byte[] { 0x48, 0x83, 0xC4, 0x28 }); if (callDescriptor.ReturnAddress != IntPtr.Zero) { // mov [returnAddress], rax shellcode.AddRange(new byte[] { 0x48, 0xA3 }); shellcode.AddRange(BitConverter.GetBytes((long)callDescriptor.ReturnAddress)); } // xor eax, eax shellcode.AddRange(new byte[] { 0x31, 0xC0 }); // ret shellcode.Add(0xC3); } return(shellcode.ToArray()); }