diff --git a/daemon/source/main.cpp b/daemon/source/main.cpp index 43b0339..7e6d137 100644 --- a/daemon/source/main.cpp +++ b/daemon/source/main.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include "dbg.hpp" @@ -185,6 +186,11 @@ static void killApp(int pid) noexcept { } } +static bool isProcessAlive(int pid) noexcept { + int mib[]{CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + return sysctl(mib, 4, nullptr, nullptr, nullptr, 0) == 0; +} + static bool handleIpc(const int syscore, const int fd) noexcept { static constexpr int PING = 0; static constexpr int PONG = 1; @@ -246,15 +252,22 @@ static bool handleIpc(const int syscore, const int fd) noexcept { dbg::Tracer tracer{pid}; auto regs = tracer.getRegisters(); regs.rip(res.func); - tracer.setRegisters(regs); + if (!tracer.setRegisters(regs)) { + puts("failed to set registers"); + } // run until execve completion tracer.run(); - while (spawned == nullptr) { - // this should grab it first try but I haven't confirmed yet + do { // NOLINT spawned = Hijacker::getHijacker(pid); - } + if (spawned == nullptr) { + if (isProcessAlive(pid)) { + puts("process died"); + return result; + } + } + } while (spawned == nullptr); const uintptr_t nanosleepOffset = getNanosleepOffset(*spawned); @@ -264,11 +277,9 @@ static bool handleIpc(const int syscore, const int fd) noexcept { puts("success"); - uintptr_t base = 0; - while (base == 0) { - // this should also work first try but not confirmed - base = spawned->getLibKernelBase(); - } + uintptr_t base = spawned->getLibKernelBase(); + + printf("libkernel imagebase: 0x%08llx\n", base); loop.setTarget(base + nanosleepOffset); base = spawned->imagebase(); diff --git a/include/elf/elf.hpp b/include/elf/elf.hpp index efe9e25..e8e3395 100644 --- a/include/elf/elf.hpp +++ b/include/elf/elf.hpp @@ -46,6 +46,8 @@ class Elf : Elf64_Ehdr { bool processPltRelocations() noexcept; bool load() noexcept; bool start(uintptr_t args) noexcept; + bool fillSymbolTables(const Array &names, int handleCount, int *preLoadedHandles) noexcept; + bool processLibs(List &neededLibs) noexcept; uintptr_t setupKernelRW() noexcept; uintptr_t getSymbolAddress(const Elf64_Rela *__restrict rel) const noexcept; diff --git a/include/hijacker/hijacker.hpp b/include/hijacker/hijacker.hpp index 1cba1b7..4140ec9 100644 --- a/include/hijacker/hijacker.hpp +++ b/include/hijacker/hijacker.hpp @@ -63,7 +63,10 @@ class Hijacker { auto obj = p->getSharedObject(); // obj may be a nullptr when racing process creation - return obj != nullptr ? new Hijacker{obj.release()} : nullptr; + if (obj != nullptr) { + return {new Hijacker{obj.release()}}; + } + return nullptr; } UniquePtr getProc() const { diff --git a/include/kernel/rtld.hpp b/include/kernel/rtld.hpp index c9752c8..454825f 100644 --- a/include/kernel/rtld.hpp +++ b/include/kernel/rtld.hpp @@ -245,13 +245,14 @@ class SharedLibIterable { int pid; public: - SharedLibIterable(decltype(nullptr)) : addr(), pid() {} - SharedLibIterable(uintptr_t addr, int pid) : addr(addr), pid(pid) {} - bool operator!=(decltype(nullptr)) const { return addr != 0; } + SharedLibIterable(decltype(nullptr)) noexcept : addr(), pid() {} + SharedLibIterable(uintptr_t addr, int pid) noexcept : addr(addr), pid(pid) {} + bool operator==(decltype(nullptr)) const noexcept { return addr == 0; } + bool operator!=(decltype(nullptr)) const noexcept { return addr != 0; } UniquePtr operator*() { - return new SharedLib{addr, pid}; + return {new SharedLib{addr, pid}}; } - SharedLibIterable &operator++() { + SharedLibIterable &operator++() noexcept { uintptr_t ptr = 0; kernel_copyout(addr, &ptr, sizeof(ptr)); addr = ptr; @@ -262,18 +263,19 @@ class SharedLibIterable { } }; -struct SharedLibIterator { +class SharedLibIterator { uintptr_t addr; int pid; - SharedLibIterator(uintptr_t addr, int pid) : addr(addr), pid(pid) {} - SharedLibIterable begin() const { - return {addr, pid}; - } - decltype(nullptr) end() const { - return nullptr; - } + public: + SharedLibIterator(uintptr_t addr, int pid) : addr(addr), pid(pid) {} + SharedLibIterable begin() const { + return {addr, pid}; + } + decltype(nullptr) end() const { + return nullptr; + } }; @@ -286,10 +288,10 @@ class SharedObject : KernelObject { public: int pid; - SharedObject(uintptr_t addr, int pid) + SharedObject(uintptr_t addr, int pid) noexcept : KernelObject(addr), eboot(nullptr), pid(pid) {} - SharedLibIterator getLibs() const { + SharedLibIterator getLibs() const noexcept { return {get(), pid}; } @@ -299,12 +301,12 @@ class SharedObject : KernelObject { if (ptr == 0) [[unlikely]] { return nullptr; } - eboot = new SharedLib{ptr, pid}; + eboot = {new SharedLib{ptr, pid}}; } return eboot.get(); } - UniquePtr getLib(int handle) const { + UniquePtr getLib(int handle) const noexcept { for (auto lib : getLibs()) { if (lib->handle() == handle) { return lib.release(); @@ -313,7 +315,7 @@ class SharedObject : KernelObject { return nullptr; } - UniquePtr getLib(const StringView &name) const { + UniquePtr getLib(const StringView &name) const noexcept { String fullname = name; if (!name.endswith(".sprx"_sv)) { fullname += ".sprx"_sv; @@ -526,10 +528,6 @@ class rtld::ElfSymbolTable { return nullptr; } - const ElfSymbol operator[](Nid &&nid) const { - return this->operator[](nid); - } - size_t length() const { return size; } @@ -542,15 +540,15 @@ class rtld::ElfSymbolTable { namespace { static inline UniquePtr newRtldMeta(uintptr_t imageBase, uintptr_t addr) { - return new RtldMeta(imageBase, addr); + return {new RtldMeta(imageBase, addr)}; } static inline UniquePtr newSymbolTable(const RtldMeta *meta) { - return new rtld::ElfSymbolTable(meta); + return {new rtld::ElfSymbolTable(meta)}; } static inline UniquePtr newStringTable(const RtldMeta *meta) { - return new rtld::ElfStringTable(meta); + return {new rtld::ElfStringTable(meta)}; } } diff --git a/libhijacker/CMakeLists.txt b/libhijacker/CMakeLists.txt index 8e76977..21d56a9 100644 --- a/libhijacker/CMakeLists.txt +++ b/libhijacker/CMakeLists.txt @@ -65,7 +65,7 @@ set(CMAKE_C_FLAGS "--target=x86_64-freebsd-pc-elf -march=znver2 -DPPR -DPS5 -DPS set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200112 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=500") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin -nostdlib -Wall") # -nostartfiles set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O3 -march=znver2 -Wall -Wextra -Wmove -Wmost -Werror -pedantic -pedantic-errors -fno-exceptions") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -DDEBUG -gfull -gdwarf-2 -O0 -march=znver2 -Wall -Wextra -Wmove -Wmost -Werror -pedantic -pedantic-errors -fno-exceptions") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g0 -O0") target_include_directories(${PROJECT_NAME} PRIVATE "${D_CWD}/../include") target_include_directories(${PROJECT_NAME} PRIVATE "${D_CWD}/../libNidResolver/include") diff --git a/libhijacker/source/elf/elf.cpp b/libhijacker/source/elf/elf.cpp index 93a1ffc..d1dcde8 100644 --- a/libhijacker/source/elf/elf.cpp +++ b/libhijacker/source/elf/elf.cpp @@ -40,7 +40,7 @@ extern "C" { namespace { -constexpr size_t NUM_PRELOADED_MODULES = 3; +constexpr size_t NUM_PRELOADED_MODULES = 2; constexpr int LIBKERNEL_HANDLE = 0x2001; constexpr int LIBC_HANDLE = 2; //constexpr int LIBSYSMODULE_HANDLE = 0X11; @@ -72,6 +72,65 @@ Elf::Elf(Hijacker *hijacker, uint8_t *data) noexcept : bool loadLibraries(Hijacker &hijacker, const dbg::Tracer &tracer, const Array &paths, ManagedResolver &resolver) noexcept; +bool Elf::fillSymbolTables(const Array &names, int handleCount, int *preLoadedHandles) noexcept { + resolver = {new ManagedResolver{}}; + resolver->reserve_library_memory(handleCount + names.length()); + + puts("filling symbol tables"); + for (auto i = 0; i < handleCount; i++) { + auto ptr = hijacker->getLib(preLoadedHandles[i]); + if (ptr == nullptr) [[unlikely]] { + printf("failed to get lib for 0x%x\n", (unsigned int) preLoadedHandles[i]); + return false; + } + if (resolver->add_library_metadata(ptr->imagebase(), ptr->getMetaDataAddress()) != 0) { + printf("failed to add library metadata for 0x%x\n", (unsigned int) preLoadedHandles[i]); + return false; + } + } + + if (names.length() > 0) { + puts("loading libraries"); + if (!loadLibraries(*hijacker, tracer, names, *resolver)) { + __builtin_printf("failed to load libraries\n"); + return false; + } + } + + puts("finished process dynamic table"); + return true; +} + +bool Elf::processLibs(List &neededLibs) noexcept { + Array names{neededLibs.length()}; + + int preLoadedHandles[NUM_PRELOADED_MODULES]; + int handleCount = 0; + size_t i = 0; + for (const Elf64_Dyn *lib : neededLibs) { + StringView filename = strtab + lib->d_un.d_val; + if (!filename.endswith(".so"_sv)) [[unlikely]] { + __builtin_printf("unexpected library 0x%llx %s\n", (unsigned long long)lib->d_un.d_val, filename.c_str()); + return false; + } + if (filename.startswith("libkernel"_sv)) { + *(preLoadedHandles + handleCount++) = LIBKERNEL_HANDLE; + continue; + } + if (filename == "libSceLibcInternal.so"_sv || filename == "libc.so"_sv) { + *(preLoadedHandles + handleCount++) = LIBC_HANDLE; + continue; + } + + names[i++] = StringView{filename.c_str(), filename.length() - 3}; + } + + // remove unset values + names.shrink(i); + + return fillSymbolTables(names, handleCount, preLoadedHandles); +} + bool Elf::parseDynamicTable() noexcept { const Elf64_Dyn *__restrict dyntbl = nullptr; for (size_t i = 0; i < e_phnum; i++) { @@ -167,63 +226,7 @@ bool Elf::parseDynamicTable() noexcept { return true; } - Array names{neededLibs.length()}; - - int preLoadedHandles[NUM_PRELOADED_MODULES]; - int handleCount = 0; - size_t i = 0; - for (const Elf64_Dyn *lib : neededLibs) { - StringView filename = strtab + lib->d_un.d_val; - if (!filename.endswith(".so"_sv)) [[unlikely]] { - __builtin_printf("unexpected library 0x%llx %s\n", (unsigned long long)lib->d_un.d_val, filename.c_str()); - return false; - } - // I really do not want to implement a hashmap - if (filename.startswith("libkernel"_sv)) { - *(preLoadedHandles + handleCount++) = LIBKERNEL_HANDLE; - continue; - } - if (filename == "libSceLibcInternal.so"_sv || filename == "libc.so"_sv) { - *(preLoadedHandles + handleCount++) = LIBC_HANDLE; - continue; - } - //if (filename == "libSceSysmodule.so"_sv) { - // *(preLoadedHandles + handleCount++) = LIBSYSMODULE_HANDLE; - // continue; - //} - - names[i++] = StringView{filename.c_str(), filename.length() - 3}; - } - - // remove unset values - names.shrink(i); - - resolver = new ManagedResolver{}; - resolver->reserve_library_memory(handleCount + names.length()); - - puts("filling symbol tables"); - for (auto i = 0; i < handleCount; i++) { - auto ptr = hijacker->getLib(preLoadedHandles[i]); - if (ptr == nullptr) [[unlikely]] { - printf("failed to get lib for 0x%x\n", (unsigned int) preLoadedHandles[i]); - return false; - } - if (resolver->add_library_metadata(ptr->imagebase(), ptr->getMetaDataAddress()) != 0) { - printf("failed to add library metadata for 0x%x\n", (unsigned int) preLoadedHandles[i]); - return false; - } - } - - if (names.length() > 0) { - puts("loading libraries"); - if (!loadLibraries(*hijacker, tracer, names, *resolver)) { - __builtin_printf("failed to load libraries\n"); - return false; - } - } - - puts("finished process dynamic table"); - return true; + return processLibs(neededLibs); } class TracedMemory { diff --git a/spawner/CMakeLists.txt b/spawner/CMakeLists.txt index 4c12779..115af41 100644 --- a/spawner/CMakeLists.txt +++ b/spawner/CMakeLists.txt @@ -62,7 +62,7 @@ set(CMAKE_C_FLAGS "--target=x86_64-freebsd-pc-elf -O0 -march=znver2 -DPPR -DPS5 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_POSIX_SOURCE -D_POSIX_C_SOURCE=200112 -D__BSD_VISIBLE=1 -D__XSI_VISIBLE=500") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-builtin -nostdlib -Wall") # -nostartfiles set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") -set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -O3 -march=znver2 -Wall -Wextra -Wmove -Wmost -Werror -pedantic -pedantic-errors -fno-exceptions -Wno-unused-function") +set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -DDEBUG -gfull -gdwarf-2 -O0 -march=znver2 -Wall -Wextra -Wmove -Wmost -Werror -pedantic -pedantic-errors -fno-exceptions -Wno-unused-function") set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wno-unused-command-line-argument") target_sources(${PROJECT_NAME} PRIVATE ${SrcFiles})