diff options
| author | auth12 <[email protected]> | 2021-07-06 23:21:34 +0100 |
|---|---|---|
| committer | auth12 <[email protected]> | 2021-07-06 23:21:34 +0100 |
| commit | 813e464a2f7a6ebfe073b1cade577f9f803ae700 (patch) | |
| tree | fbe765e26ba39db34979bec773d24bfe5256a85a | |
| parent | replaced CreateRemoteThread (diff) | |
| download | sysmap-813e464a2f7a6ebfe073b1cade577f9f803ae700.tar.xz sysmap-813e464a2f7a6ebfe073b1cade577f9f803ae700.zip | |
Replaced create thread with thread hijacking
| -rw-r--r-- | sysmap/src/main.cpp | 17 | ||||
| -rw-r--r-- | sysmap/src/mapper/process.h | 114 | ||||
| -rw-r--r-- | sysmap/sysmap.vcxproj | 8 |
3 files changed, 120 insertions, 19 deletions
diff --git a/sysmap/src/main.cpp b/sysmap/src/main.cpp index 4c73340..d775e6c 100644 --- a/sysmap/src/main.cpp +++ b/sysmap/src/main.cpp @@ -24,17 +24,20 @@ int main(int argc, char* argv[]) { if (args.size() < 2) { io::log<critical>("Invalid arguments specified."); + std::cin.get(); + return 0; } - spdlog::set_pattern("[%^%l%$] %v"); - for (auto& arg : args) { if (arg == "--debug") { spdlog::set_level(spdlog::level::debug); } } + spdlog::set_pattern("[%^%l%$] %v"); + spdlog::set_level(spdlog::level::debug); + g_ctx.local_modules = std::move(util::get_modules()); auto ntdll = g_ctx.local_modules[1]; @@ -45,13 +48,21 @@ int main(int argc, char* argv[]) { io::log<info>("waiting for {}", args[0]); + auto buf = io::read_file(args[1]); + if (buf.empty()) { + io::log<critical>("failed to read file."); + std::cin.get(); + + return 0; + } + process::process_x64_t proc; if (NT_SUCCESS(proc.attach(args[0]))) { io::log<info>("attached!"); proc.modules = proc.get_modules(); - proc.map(io::read_file(args[1])); + proc.map(buf); proc.close(proc.handle); } diff --git a/sysmap/src/mapper/process.h b/sysmap/src/mapper/process.h index 9d6da35..ba37585 100644 --- a/sysmap/src/mapper/process.h +++ b/sysmap/src/mapper/process.h @@ -2,9 +2,60 @@ namespace process { + struct thread_t { + SYSTEM_THREAD_INFORMATION info; + HANDLE handle; + + NTSTATUS open() { + static auto nt_open_thread = g_syscalls.get<decltype(&NtOpenThread)>("NtOpenThread"); + CLIENT_ID cid; + cid.UniqueProcess = 0; + cid.UniqueThread = info.ClientId.UniqueThread; + + OBJECT_ATTRIBUTES oa; + oa.Length = sizeof(oa); + oa.Attributes = 0; + oa.RootDirectory = 0; + oa.SecurityDescriptor = 0; + oa.ObjectName = 0; + oa.SecurityQualityOfService = 0; + + auto ret = nt_open_thread(&handle, THREAD_ALL_ACCESS, &oa, &cid); + + io::log<debug>("NtOpenThread on {}, returned {:x}.", uintptr_t(cid.UniqueThread), ret & 0xFFFFFFFF); + + return ret; + } + + NTSTATUS suspend() { + static auto nt_suspend = g_syscalls.get<decltype(&NtSuspendThread)>("NtSuspendThread"); + + return nt_suspend(handle, nullptr); + } + + NTSTATUS resume() { + static auto nt_resume = g_syscalls.get<decltype(&NtResumeThread)>("NtResumeThread"); + + return nt_resume(handle, nullptr); + } + + NTSTATUS get_ctx(CONTEXT* out) { + static auto nt_get_ctx = g_syscalls.get<decltype(&NtGetContextThread)>("NtGetContextThread"); + + return nt_get_ctx(handle, out); + } + + NTSTATUS set_ctx(CONTEXT *ctx) { + static auto nt_set_ctx = g_syscalls.get<decltype(&NtSetContextThread)>("NtSetContextThread"); + + return nt_set_ctx(handle, ctx); + } + }; + struct process_info_t { std::string name; u16 pid; + std::vector<thread_t> threads; }; struct process_iterator { @@ -49,7 +100,19 @@ namespace process { continue; } - out.emplace_back(process_info_t{ util::to_multibyte(s), reinterpret_cast<u16>(pi->UniqueProcessId) }); + process_info_t ret; + ret.name = util::to_multibyte(s); + ret.pid = PtrToUshort(pi->UniqueProcessId); + + auto ti = reinterpret_cast<SYSTEM_THREAD_INFORMATION*>(pi->Threads); + for (int i = 0; i < pi->NumberOfThreads; i++) { + thread_t t; + std::memcpy(&t.info, &ti[i], sizeof(SYSTEM_THREAD_INFORMATION)); + + ret.threads.emplace_back(t); + } + + out.emplace_back(std::move(ret)); ptr = iter.get_next(); } @@ -63,9 +126,12 @@ namespace process { std::vector<util::module_data_t> modules; - NTSTATUS open_handle() { + NTSTATUS open() { static auto nt_open = g_syscalls.get<decltype(&NtOpenProcess)>("NtOpenProcess"); - CLIENT_ID cid = { HANDLE(info.pid), 0 }; + CLIENT_ID cid; + cid.UniqueProcess = HANDLE(info.pid); + cid.UniqueThread = 0; + OBJECT_ATTRIBUTES oa; oa.Length = sizeof(oa); oa.Attributes = 0; @@ -99,7 +165,7 @@ namespace process { info = *it; - return open_handle(); + return open(); } NTSTATUS read(uintptr_t addr, void* buf, size_t size) { @@ -160,7 +226,7 @@ namespace process { return nt_create(out, THREAD_ALL_ACCESS, nullptr, handle, reinterpret_cast<LPTHREAD_START_ROUTINE>(start), 0, 0x4, 0, 0, 0, 0); } - NTSTATUS wait(HANDLE h) { + static NTSTATUS wait(HANDLE h) { static auto nt_wait = g_syscalls.get<decltype(&NtWaitForSingleObject)>("NtWaitForSingleObject"); return nt_wait(h, false, nullptr); @@ -446,12 +512,14 @@ namespace process { return {}; } - static std::vector<u8> shellcode = { 0x48, 0x83, 0xEC, 0x28, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC2,0x01, 0x00, 0x00, 0x00, 0x4D, 0x31, 0xC0, - 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xD0, 0x48, 0x83, 0xC4, 0x28, 0xC3 }; + std::vector<u8> shellcode = { 0x9C, 0x50, 0x53, 0x51, 0x52, 0x55, 0x56, 0x57, 0x41, 0x50, 0x41, 0x51, 0x41, 0x52, 0x41, 0x53, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, + 0x28, 0x48, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xC7, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x4D, 0x31, 0xC0, 0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, + 0xD0, 0x48, 0x83, 0xC4, 0x28, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5F, 0x5E, 0x5D, 0x5A, 0x59, 0x5B, 0x58, 0x9D, 0xc3 }; + + *reinterpret_cast<u64*>(&shellcode[30]) = allocation_base; + *reinterpret_cast<u64*>(&shellcode[50]) = allocation_base + nt->optional_header.entry_point - headers_size; - *reinterpret_cast<u64*>(&shellcode[6]) = allocation_base; - *reinterpret_cast<u64*>(&shellcode[26]) = allocation_base + nt->optional_header.entry_point - headers_size; + io::log<debug>("entry {:x}", allocation_base + nt->optional_header.entry_point - headers_size); uintptr_t shellcode_base; alloc(&shellcode_base, shellcode.size(), MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -460,9 +528,29 @@ namespace process { write(shellcode_base, shellcode.data(), shellcode.size()); - HANDLE thread_handle; - create_thread(shellcode_base, &thread_handle); - wait(thread_handle); + for (auto& t : info.threads) { + if (t.info.ThreadState == Waiting) { + io::log<log_lvl::info>("found viable thread {}, hijacking...", uintptr_t(t.info.ClientId.UniqueThread)); + + CONTEXT ctx; + ctx.ContextFlags = CONTEXT_FULL; + + t.open(); + t.suspend(); + t.get_ctx(&ctx); + + io::log<debug>("thread RIP: {:x}", ctx.Rip); + io::log<debug>("thread stack pointer: {:x}", ctx.Rsp); + + ctx.Rip = shellcode_base; + + t.set_ctx(&ctx); + t.resume(); + + close(t.handle); + break; + } + } io::log<log_lvl::info>("mapped target image"); diff --git a/sysmap/sysmap.vcxproj b/sysmap/sysmap.vcxproj index a42f5d0..dc6b77d 100644 --- a/sysmap/sysmap.vcxproj +++ b/sysmap/sysmap.vcxproj @@ -81,9 +81,10 @@ </PropertyGroup> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <LinkIncremental>false</LinkIncremental> - <OutDir>$(SolutionDir)bin\$(Platform)\$(Configuration)\</OutDir> - <IntDir>obj\$(Platform)\$(Configuration)\</IntDir> + <OutDir>$(SolutionDir)bin\$(Configuration)\$(Platform)\</OutDir> + <IntDir>obj\$(Configuration)\$(Platform)\</IntDir> <IncludePath>$(SolutionDir)modules\phnt\;$(SolutionDir)modules\linuxpe\includes\;$(SolutionDir)modules\spdlog\include\;$(IncludePath)</IncludePath> + <LibraryPath>$(LibraryPath)</LibraryPath> </PropertyGroup> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ClCompile> @@ -141,7 +142,8 @@ <EnableCOMDATFolding>true</EnableCOMDATFolding> <OptimizeReferences>true</OptimizeReferences> <GenerateDebugInformation>true</GenerateDebugInformation> - <UACExecutionLevel>RequireAdministrator</UACExecutionLevel> + <UACExecutionLevel>AsInvoker</UACExecutionLevel> + <AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies> </Link> </ItemDefinitionGroup> <ItemGroup> |