示例#1
0
        internal TStructure CallFunction <TStructure>(CallingConvention callingConvention, IntPtr functionAddress, params long[] parameters) where TStructure : unmanaged
        {
            var returnBuffer = Memory.Allocate(Unsafe.SizeOf <TStructure>(), ProtectionType.ReadWrite);

            // Write the shellcode used to perform the function call into a buffer in the remote process

            var shellcode = Assembler.AssembleCallDescriptor(new CallDescriptor(functionAddress, callingConvention, IsWow64, parameters, returnBuffer));

            var shellcodeBuffer = Memory.Allocate(shellcode.Length, ProtectionType.ExecuteReadWrite);

            Memory.Write(shellcodeBuffer, shellcode);

            // Create a thread in the remote process to execute the shellcode

            var ntStatus = Ntdll.RtlCreateUserThread(_processHandle, IntPtr.Zero, false, 0, IntPtr.Zero, IntPtr.Zero, shellcodeBuffer, IntPtr.Zero, out var threadHandle, IntPtr.Zero);

            if (ntStatus != NtStatus.Success)
            {
                throw new Win32Exception($"Failed to call RtlCreateUserThread with error code {Ntdll.RtlNtStatusToDosError(ntStatus)}");
            }

            if (Kernel32.WaitForSingleObject(threadHandle, int.MaxValue) == -1)
            {
                throw new Win32Exception($"Failed to call WaitForSingleObject with error code {Marshal.GetLastWin32Error()}");
            }

            threadHandle.Dispose();

            Memory.Free(shellcodeBuffer);

            try
            {
                return(Memory.Read <TStructure>(returnBuffer));
            }

            finally
            {
                Memory.Free(returnBuffer);
            }
        }