示例#1
0
        internal T CallRoutine <T>(IntPtr routineAddress, params dynamic[] arguments) where T : unmanaged
        {
            var returnAddress = Process.AllocateMemory(Unsafe.SizeOf <T>());

            // Create the shellcode used to call the routine

            Span <byte> shellcodeBytes;

            if (Process.GetArchitecture() == Architecture.X86)
            {
                var callDescriptor = new CallDescriptor32(routineAddress, Array.ConvertAll(arguments, argument => (int)argument), returnAddress);

                shellcodeBytes = CallAssembler.AssembleCall32(callDescriptor);
            }

            else
            {
                var routineDescriptor = new CallDescriptor64(routineAddress, Array.ConvertAll(arguments, argument => (long)argument), returnAddress);

                shellcodeBytes = CallAssembler.AssembleCall64(routineDescriptor);
            }

            try
            {
                // Write the shellcode bytes into the process

                var shellcodeBytesAddress = Process.AllocateMemory(shellcodeBytes.Length, true);

                try
                {
                    Process.WriteArray(shellcodeBytesAddress, shellcodeBytes);

                    // Create a thread to execute the shellcode

                    Process.CreateThread(shellcodeBytesAddress);
                }

                finally
                {
                    Process.FreeMemory(shellcodeBytesAddress);
                }

                return(Process.ReadStructure <T>(returnAddress));
            }

            finally
            {
                Process.FreeMemory(returnAddress);
            }
        }
示例#2
0
        internal void CallRoutine(IntPtr routineAddress, params dynamic[] arguments)
        {
            // Create the shellcode used to call the routine

            Span <byte> shellcodeBytes;

            if (Process.GetArchitecture() == Architecture.X86)
            {
                var callDescriptor = new CallDescriptor32(routineAddress, Array.ConvertAll(arguments, argument => (int)argument), IntPtr.Zero);

                shellcodeBytes = CallAssembler.AssembleCall32(callDescriptor);
            }

            else
            {
                var routineDescriptor = new CallDescriptor64(routineAddress, Array.ConvertAll(arguments, argument => (long)argument), IntPtr.Zero);

                shellcodeBytes = CallAssembler.AssembleCall64(routineDescriptor);
            }

            // Write the shellcode bytes into the process

            var shellcodeBytesAddress = Process.AllocateMemory(shellcodeBytes.Length, true);

            try
            {
                Process.WriteArray(shellcodeBytesAddress, shellcodeBytes);

                // Create a thread to execute the shellcode

                Process.CreateThread(shellcodeBytesAddress);
            }

            finally
            {
                Process.FreeMemory(shellcodeBytesAddress);
            }
        }
示例#3
0
        internal static Span <byte> AssembleCall64(CallDescriptor64 callDescriptor)
        {
            var instructions = new List <byte>();

            var shadowSpaceSize = Constants.ShadowSpaceSize + Math.Max(0, callDescriptor.Arguments.Count - 4);

            // sub rsp, shadowSpaceSize

            instructions.AddRange(new byte[] { 0x48, 0x83, 0xEC, (byte)shadowSpaceSize });

            if (callDescriptor.Arguments.Count > 0)
            {
                var argument = callDescriptor.Arguments[0];

                switch (argument)
                {
                case 0:
                {
                    // xor ecx, ecx

                    instructions.AddRange(new byte[] { 0x31, 0xC9 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov ecx, argument

                    instructions.Add(0xB9);

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rcx, argument

                    instructions.AddRange(new byte[] { 0x48, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 1)
            {
                var argument = callDescriptor.Arguments[1];

                switch (argument)
                {
                case 0:
                {
                    // xor edx, edx

                    instructions.AddRange(new byte[] { 0x31, 0xD2 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov edx, argument

                    instructions.Add(0xBA);

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rdx, argument

                    instructions.AddRange(new byte[] { 0x48, 0xBA });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 2)
            {
                var argument = callDescriptor.Arguments[2];

                switch (argument)
                {
                case 0:
                {
                    // xor r8, r8

                    instructions.AddRange(new byte[] { 0x4D, 0x31, 0xC0 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov r8d, argument

                    instructions.AddRange(new byte[] { 0x41, 0xB8 });

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r8, argument

                    instructions.AddRange(new byte[] { 0x49, 0xB8 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 3)
            {
                var argument = callDescriptor.Arguments[3];

                switch (argument)
                {
                case 0:
                {
                    // xor r9, r9

                    instructions.AddRange(new byte[] { 0x4D, 0x31, 0xC9 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov r9d, argument

                    instructions.AddRange(new byte[] { 0x41, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r9, argument

                    instructions.AddRange(new byte[] { 0x49, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Count > 4)
            {
                foreach (var argument in callDescriptor.Arguments.Skip(4).Reverse())
                {
                    switch (argument)
                    {
                    case <= sbyte.MaxValue:
                    {
                        // push argument

                        instructions.AddRange(new byte[] { 0x6A, (byte)argument });

                        break;
                    }

                    case <= uint.MaxValue:
                    {
                        // push argument

                        instructions.Add(0x68);

                        instructions.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov rax, argument

                        instructions.AddRange(new byte[] { 0x48, 0xB8 });

                        instructions.AddRange(BitConverter.GetBytes(argument));

                        // push rax

                        instructions.Add(0x50);

                        break;
                    }
                    }
                }
            }

            // mov rax, Address

            instructions.AddRange(new byte[] { 0x48, 0xB8 });

            instructions.AddRange(BitConverter.GetBytes(callDescriptor.Address.ToInt64()));

            // call rax

            instructions.AddRange(new byte[] { 0xFF, 0xD0 });

            if (callDescriptor.ReturnAddress != IntPtr.Zero)
            {
                // mov ReturnAddress, rax

                instructions.AddRange(new byte[] { 0x48, 0xA3 });

                instructions.AddRange(BitConverter.GetBytes(callDescriptor.ReturnAddress.ToInt64()));
            }

            // xor eax, eax

            instructions.AddRange(new byte[] { 0x31, 0xC0 });

            // add rsp, shadowSpaceSize

            instructions.AddRange(new byte[] { 0x48, 0x83, 0xC4, (byte)shadowSpaceSize });

            // ret

            instructions.Add(0xC3);

            return(CollectionsMarshal.AsSpan(instructions));
        }
示例#4
0
        internal static Span <byte> AssembleCall64(CallDescriptor64 callDescriptor)
        {
            var instructions = new List <byte>();

            // sub rsp, 0x28

            instructions.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x28 });

            foreach (var(argument, argumentIndex) in callDescriptor.Arguments.Select((argument, argumentIndex) => (argument, argumentIndex)))
            {
                switch (argumentIndex)
                {
                case 0:
                {
                    switch (argument)
                    {
                    case 0:
                    {
                        // xor ecx, ecx

                        instructions.AddRange(new byte[] { 0x31, 0xC9 });

                        break;
                    }

                    case <= uint.MaxValue:
                    {
                        // mov ecx, argument

                        instructions.Add(0xB9);

                        instructions.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov rcx, argument

                        instructions.AddRange(new byte[] { 0x48, 0xB9 });

                        instructions.AddRange(BitConverter.GetBytes(argument));

                        break;
                    }
                    }

                    break;
                }

                case 1:
                {
                    switch (argument)
                    {
                    case 0:
                    {
                        // xor edx, edx

                        instructions.AddRange(new byte[] { 0x31, 0xD2 });

                        break;
                    }

                    case <= uint.MaxValue:
                    {
                        // mov edx, argument

                        instructions.Add(0xBA);

                        instructions.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov rdx, argument

                        instructions.AddRange(new byte[] { 0x48, 0xBA });

                        instructions.AddRange(BitConverter.GetBytes(argument));

                        break;
                    }
                    }

                    break;
                }

                case 2:
                {
                    switch (argument)
                    {
                    case 0:
                    {
                        // xor r8d, r8d

                        instructions.AddRange(new byte[] { 0x45, 0x31, 0xC0 });

                        break;
                    }

                    case <= uint.MaxValue:
                    {
                        // mov r8d, argument

                        instructions.AddRange(new byte[] { 0x41, 0xB8 });

                        instructions.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov r8, argument

                        instructions.AddRange(new byte[] { 0x49, 0xB8 });

                        instructions.AddRange(BitConverter.GetBytes(argument));

                        break;
                    }
                    }

                    break;
                }

                case 3:
                {
                    switch (argument)
                    {
                    case 0:
                    {
                        // xor r9d, r9d

                        instructions.AddRange(new byte[] { 0x45, 0x31, 0xC9 });

                        break;
                    }

                    case <= uint.MaxValue:
                    {
                        // mov r9d, argument

                        instructions.AddRange(new byte[] { 0x41, 0xB9 });

                        instructions.AddRange(BitConverter.GetBytes((int)argument));

                        break;
                    }

                    default:
                    {
                        // mov r9, argument

                        instructions.AddRange(new byte[] { 0x49, 0xB9 });

                        instructions.AddRange(BitConverter.GetBytes(argument));

                        break;
                    }
                    }

                    break;
                }
                }
            }

            // mov rax, Address

            instructions.AddRange(new byte[] { 0x48, 0xB8 });

            instructions.AddRange(BitConverter.GetBytes(callDescriptor.Address.ToInt64()));

            // call rax

            instructions.AddRange(new byte[] { 0xFF, 0xD0 });

            if (callDescriptor.ReturnAddress != IntPtr.Zero)
            {
                // mov ReturnAddress, rax

                instructions.AddRange(new byte[] { 0x48, 0xA3 });

                instructions.AddRange(BitConverter.GetBytes(callDescriptor.ReturnAddress.ToInt64()));
            }

            // xor eax, eax

            instructions.AddRange(new byte[] { 0x31, 0xC0 });

            // add rsp, 0x28

            instructions.AddRange(new byte[] { 0x48, 0x83, 0xC4, 0x28 });

            // ret

            instructions.Add(0xC3);

            return(instructions.ToArray());
        }
示例#5
0
        internal static Span <byte> AssembleCall64(CallDescriptor64 callDescriptor)
        {
            var instructions = new List <byte>();

            // sub rsp, 0x28

            instructions.AddRange(new byte[] { 0x48, 0x83, 0xEC, 0x28 });

            if (callDescriptor.Arguments.Length > 0)
            {
                var argument = callDescriptor.Arguments[0];

                switch (argument)
                {
                case 0:
                {
                    // xor ecx, ecx

                    instructions.AddRange(new byte[] { 0x31, 0xC9 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov ecx, argument

                    instructions.Add(0xB9);

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rcx, argument

                    instructions.AddRange(new byte[] { 0x48, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Length > 1)
            {
                var argument = callDescriptor.Arguments[1];

                switch (argument)
                {
                case 0:
                {
                    // xor edx, edx

                    instructions.AddRange(new byte[] { 0x31, 0xD2 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov edx, argument

                    instructions.Add(0xBA);

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov rdx, argument

                    instructions.AddRange(new byte[] { 0x48, 0xBA });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Length > 2)
            {
                var argument = callDescriptor.Arguments[2];

                switch (argument)
                {
                case 0:
                {
                    // xor r8d, r8d

                    instructions.AddRange(new byte[] { 0x45, 0x31, 0xC0 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov r8d, argument

                    instructions.AddRange(new byte[] { 0x41, 0xB8 });

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r8, argument

                    instructions.AddRange(new byte[] { 0x49, 0xB8 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Length > 3)
            {
                var argument = callDescriptor.Arguments[3];

                switch (argument)
                {
                case 0:
                {
                    // xor r9d, r9d

                    instructions.AddRange(new byte[] { 0x45, 0x31, 0xC9 });

                    break;
                }

                case <= uint.MaxValue:
                {
                    // mov r9d, argument

                    instructions.AddRange(new byte[] { 0x41, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes((int)argument));

                    break;
                }

                default:
                {
                    // mov r9, argument

                    instructions.AddRange(new byte[] { 0x49, 0xB9 });

                    instructions.AddRange(BitConverter.GetBytes(argument));

                    break;
                }
                }
            }

            if (callDescriptor.Arguments.Length > 4)
            {
                foreach (var argument in callDescriptor.Arguments[4..].Reverse())