diff --git a/README.md b/README.md index 9b26cac..9169602 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ -# pclone +# pclone (Process Cloning) -Process Cloning \ No newline at end of file +pclone is small project designed to clone running processes. The cloning does not clone threads nor handles, it does however clone all virtual memory. +It does this by swapping dirbase in the clones EPROCESS structure. It also swaps the PEB in the EPROCESS structure so the clone will list the same loaded modules +as the cloned process. \ No newline at end of file diff --git a/pclone/main.cpp b/pclone/main.cpp index 46ced50..9f12dc9 100644 --- a/pclone/main.cpp +++ b/pclone/main.cpp @@ -55,15 +55,15 @@ int __cdecl main(int argc, char** argv) vdm.set_read(_read_phys); vdm.set_write(_write_phys); - nasa::mem_ctx notepad_proc(vdm, std::atoi(argv[2])); - nasa::pclone_ctx clone_notepad(¬epad_proc); - const auto [clone_pid, clone_handle] = clone_notepad.clone(); + nasa::mem_ctx target_proc(vdm, std::atoi(argv[2])); + nasa::pclone_ctx clone_ctx(&target_proc); + const auto [clone_pid, clone_handle] = clone_ctx.clone(); unsigned short mz = 0u; std::size_t bytes_read; ReadProcessMemory(clone_handle, GetModuleHandleA("ntdll.dll"), &mz, sizeof mz, &bytes_read); std::printf("[+] handle -> 0x%x, clone pid -> 0x%x\n", clone_handle, clone_pid); - std::printf("[+] notepad mz -> 0x%x\n", mz); + std::printf("[+] ntdll mz in clone -> 0x%x\n", mz); std::getchar(); } \ No newline at end of file diff --git a/pclone/mem_ctx/mem_ctx.cpp b/pclone/mem_ctx/mem_ctx.cpp index 8d84258..27abee6 100644 --- a/pclone/mem_ctx/mem_ctx.cpp +++ b/pclone/mem_ctx/mem_ctx.cpp @@ -73,13 +73,6 @@ namespace nasa this->new_pt.first = reinterpret_cast(new_pt_entries.pt.second.pfn << 12); } - mem_ctx::~mem_ctx() - { - const auto pml4 = - reinterpret_cast( - set_page(dirbase))[pml4e_index] = pml4e{ NULL }; - } - void* mem_ctx::set_page(void* addr) { // table entry change. diff --git a/pclone/mem_ctx/mem_ctx.hpp b/pclone/mem_ctx/mem_ctx.hpp index f20447b..22a7ca2 100644 --- a/pclone/mem_ctx/mem_ctx.hpp +++ b/pclone/mem_ctx/mem_ctx.hpp @@ -9,8 +9,6 @@ namespace nasa friend class pclone_ctx; public: mem_ctx(vdm::vdm_ctx& v_ctx, std::uint32_t pid = GetCurrentProcessId()); - ~mem_ctx(); - std::pair get_pte(void* addr, bool use_hyperspace = false); void set_pte(void* addr, const ::pte& pte, bool use_hyperspace = false); diff --git a/pclone/pclone_ctx/pclone_ctx.cpp b/pclone/pclone_ctx/pclone_ctx.cpp index ffa6362..d4fe9c0 100644 --- a/pclone/pclone_ctx/pclone_ctx.cpp +++ b/pclone/pclone_ctx/pclone_ctx.cpp @@ -1,4 +1,4 @@ -#include "pclone_ctx.hpp" +#include "pclone_ctx.hpp" namespace nasa { @@ -7,67 +7,67 @@ namespace nasa clone_target_ctx(clone_ctx) {} - pclone_ctx::~pclone_ctx() - { - delete clone_source_ctx; - } - auto pclone_ctx::clone() -> std::pair { - const auto runtime_broker_pid = + const auto runtime_broker_pid = util::start_runtime_broker(); - const auto runtime_broker_handle = + const auto runtime_broker_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, runtime_broker_pid); const auto v_ctx = clone_target_ctx->v_ctx; - clone_source_ctx = new mem_ctx( - *v_ctx, runtime_broker_pid); - - if (!this->sync()) - return { {}, {} }; - // zombie the the process by incrementing an exit counter // then calling TerminateProcess so the process never closes... - const auto runtime_broker_peproc = - v_ctx->get_peprocess(runtime_broker_pid); + const auto runtime_broker_peproc = + reinterpret_cast( + v_ctx->get_peprocess(runtime_broker_pid)); - static const auto inc_ref_counter = + static const auto inc_ref_counter = util::get_kmodule_export( "ntoskrnl.exe", "PsAcquireProcessExitSynchronization" ); - const auto result = - v_ctx->syscall( + const auto result = + v_ctx->syscall( inc_ref_counter, runtime_broker_peproc); - TerminateProcess(runtime_broker_handle, NULL); - return { runtime_broker_pid, runtime_broker_handle }; - } + if (result != STATUS_SUCCESS) + return { {}, {} }; - bool pclone_ctx::sync() const - { - // do not remove... - std::printf("[+] clone target dirbase -> 0x%p\n", clone_target_ctx->get_dirbase()); - const auto target_pml4 = - clone_target_ctx->set_page( - clone_target_ctx->get_dirbase()); + if (!TerminateProcess(runtime_broker_handle, NULL)) + return { {}, {} }; + + // change the _KPROCESS.DirectoryTableBase to the + // DirectoryTableBase of the process wanting to be + // cloned... + const auto clone_target_peproc = + reinterpret_cast( + v_ctx->get_peprocess(clone_target_ctx->get_pid())); - // do not remove... - std::printf("[+] clone source dirbase -> 0x%p\n", clone_source_ctx->get_dirbase()); - const auto source_pml4 = - clone_source_ctx->set_page( - clone_source_ctx->get_dirbase()); + const auto clone_target_dirbase = + v_ctx->rkm(clone_target_peproc + 0x28); - __try - { - memcpy(source_pml4, target_pml4, PAGE_4KB); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return false; - } - return true; + // change dirbase of runtime broker to the dirbase of the desired process... + v_ctx->wkm(runtime_broker_peproc + 0x28, clone_target_dirbase); + + // get the peb offset inside dirbase... + // .text:00000001403387B0 public PsGetProcessPeb + // .text:00000001403387B0 PsGetProcessPeb proc near; + // .text:00000001403387B0 48 8B 81 50 05 00 00 mov rax, [rcx + 550h] <==== + 3 bytes here... + // .text:00000001403387B7 C3 retn + // .text:00000001403387B7 PsGetProcessPeb endp + const auto eprocess_peb_offset = + *reinterpret_cast( + reinterpret_cast( + GetProcAddress(GetModuleHandleA( + "ntoskrnl.exe"), "PsGetProcessPeb")) + 0x3); // <==== + 3 bytes here... + + const auto clone_target_peb = + v_ctx->rkm( + clone_target_peproc + eprocess_peb_offset); + + v_ctx->wkm(runtime_broker_peproc + eprocess_peb_offset, clone_target_peb); + return { runtime_broker_pid, runtime_broker_handle }; } } \ No newline at end of file diff --git a/pclone/pclone_ctx/pclone_ctx.hpp b/pclone/pclone_ctx/pclone_ctx.hpp index 1b61036..d1da464 100644 --- a/pclone/pclone_ctx/pclone_ctx.hpp +++ b/pclone/pclone_ctx/pclone_ctx.hpp @@ -7,11 +7,8 @@ namespace nasa friend class mem_ctx; public: explicit pclone_ctx(mem_ctx* clone_ctx); - ~pclone_ctx(); auto clone() -> std::pair; - bool sync() const; private: mem_ctx* clone_target_ctx; - mem_ctx* clone_source_ctx; }; } \ No newline at end of file diff --git a/pclone/small.ico b/pclone/small.ico index ce58e66..01d4efc 100644 Binary files a/pclone/small.ico and b/pclone/small.ico differ