diff --git a/daemon/source/main.cpp b/daemon/source/main.cpp index 5675076..dcafbba 100644 --- a/daemon/source/main.cpp +++ b/daemon/source/main.cpp @@ -15,6 +15,7 @@ #include "elf/elf.hpp" #include "fd.hpp" #include "hijacker/hijacker.hpp" +#include "msg.hpp" #include "servers.hpp" #include "util.hpp" @@ -188,6 +189,7 @@ static bool handleIpc(const int syscore, const int fd) noexcept { static constexpr int PING = 0; static constexpr int PONG = 1; static constexpr int PROCESS_LAUNCHED = 1; + static constexpr uint32_t BREW_PREFIX = 0x57455242; bool result = true; @@ -195,6 +197,7 @@ static bool handleIpc(const int syscore, const int fd) noexcept { int cmd; int pid; uintptr_t func; + unsigned int prefix; } res{}; if (recv(fd, &res, sizeof(res), MSG_NOSIGNAL) == -1) { @@ -221,8 +224,20 @@ static bool handleIpc(const int syscore, const int fd) noexcept { result = false; - LoopBuilder loop = SLEEP_LOOP; const int pid = res.pid; + const auto prefix = res.prefix; + const bool isHomebrew = res.func != 0; + if (notifyHandlers(prefix, pid, isHomebrew)) { + // elf loading has been handled by another loader + return result; + } + + if (!isHomebrew && prefix != BREW_PREFIX) { + // handlers notified, not homebrew, nothing else to do + return result; + } + + LoopBuilder loop = SLEEP_LOOP; UniquePtr spawned = nullptr; { @@ -331,6 +346,8 @@ static void *hookThread(void *args) noexcept { return 0; } +// TODO: maybe use sceLncUtilDeclareReadyForSuspend to handle rest mode + int main() { puts("daemon entered"); AbortServer abortServer{}; @@ -339,6 +356,7 @@ int main() { pthread_t elfHandler = nullptr; UniquePtr serverSock{new UnixSocket{"/system_tmp/IPC"}}; pthread_create(&elfHandler, nullptr, hookThread, serverSock.get()); + auto msgThread = startMessageReceiver(); abortServer.TcpServer::run(); klogServer.TcpServer::run(); diff --git a/daemon/source/msg.cpp b/daemon/source/msg.cpp new file mode 100644 index 0000000..a0ab5d4 --- /dev/null +++ b/daemon/source/msg.cpp @@ -0,0 +1,160 @@ +#include +#include +#include +#include +#include +#include "msg.hpp" +#include "thread.hpp" +#include "util.hpp" + +extern "C" void sceLncUtilGetAppTitleId(uint32_t appId, char *titleId); + +class LaunchListeners { + + // I should have made this a set + // realistically these will be small though + Vector appIds{}; + mutable Mutex mtx{}; + + public: + void append(const uint32_t appId) noexcept { + auto lock = mtx.lock(); + for (const auto id :appIds) { + if (id == appId) { + return; + } + } + appIds.push_back(appId); + } + + void remove(const uint32_t appId) noexcept { + auto lock = mtx.lock(); + for (const auto &id :appIds) { + if (id == appId) { + appIds.erase(&id); + return; + } + } + } + + void handle(const pid_t pid) noexcept { + auto lock = mtx.lock(); + size_t length = appIds.size(); + for (int i = 0; i < length; i++) { + const auto &id = appIds[i]; + if (sceAppMessagingSendMsg(id, BREW_MSG_TYPE_APP_LAUNCHED, &pid, sizeof(pid), 0) != 0) { + i--; + length--; + appIds.erase(&id); + } + } + } +}; + +struct RegisteredPrefix { + uint32_t appId; + uint32_t prefix; +}; + +class PrefixHandlers { + + Vector ids{}; + mutable Mutex mtx{}; + + public: + void append(uint32_t appId, uint32_t prefix) noexcept { + auto lock = mtx.lock(); + for (const auto &id : ids) { + constexpr auto TITLEID_SIZE = 9; + char titleId[TITLEID_SIZE + 1]{}; + if (id.prefix == prefix) { + sceLncUtilGetAppTitleId(appId, titleId); + char sPrefix[sizeof(prefix) + 1]; + *reinterpret_cast(sPrefix) = prefix; + sPrefix[sizeof(sPrefix) - 1] = '\0'; + printf("%s already registered to handle prefix %s\n", titleId, sPrefix); + return; + } + } + ids.emplace_back(appId, prefix); + } + + bool handle(const uint32_t prefix, const pid_t pid) noexcept { + auto lock = mtx.lock(); + size_t length = ids.size(); + for (int i = 0; i < length; i++) { + const auto &id = ids[i]; + if (id.prefix == prefix) { + if (sceAppMessagingSendMsg(id.appId, BREW_MSG_TYPE_APP_LAUNCHED, &pid, sizeof(pid), 0) != 0) { + i--; + length--; + ids.erase(&id); + } + return true; + } + } + return false; + } + + bool canHandle(const uint32_t prefix) const noexcept { + auto lock = mtx.lock(); + for (const auto &id : ids) { + if (id.prefix == prefix) { + return true; + } + } + return false; + } +}; + +static PrefixHandlers prefixHandlers{}; // NOLINT +static LaunchListeners launchListeners{}; // NOLINT + +static int messageThread(void *unused) noexcept { + (void)unused; + static AppMessage msg{}; + + while (true) { + if (sceAppMessagingReceiveMsg(&msg) < 0) { + puts("sceAppMessagingReceiveMsg failed"); + } + printf("received msg from 0x%04x\n", msg.sender); + printf("msgType: 0x%x\n", msg.msgType); + printf("payloadSize: 0x%x\n", msg.payloadSize); + switch (msg.msgType) { + case BREW_MSG_TYPE_REGISTER_PREFIX_HANDLER: { + prefixHandlers.append(msg.sender, *reinterpret_cast(msg.payload)); + break; + } + case BREW_MSG_TYPE_REGISTER_LAUNCH_LISTENER: + if (*msg.payload) { + launchListeners.append(msg.sender); + } else { + launchListeners.remove(msg.sender); + } + break; + default: + puts("unexpected msgType"); + break; + } + } + return 0; +} + +JThread startMessageReceiver() noexcept { + return JThread{messageThread}; +} + +bool notifyHandlers(const uint32_t prefix, const pid_t pid, const bool isHomebrew) noexcept { + if (isHomebrew) { + // prefix handlers are notified first since they are responsible for loading the elf if applicable + // listeners need not be notified + return prefixHandlers.handle(prefix, pid); + } + launchListeners.handle(pid); + return false; +} + +bool hasPrefixHandler(const uint32_t prefix) noexcept { + return prefixHandlers.canHandle(prefix); +} diff --git a/daemon/source/msg.hpp b/daemon/source/msg.hpp new file mode 100644 index 0000000..e460fdf --- /dev/null +++ b/daemon/source/msg.hpp @@ -0,0 +1,30 @@ +#pragma once + +#include +#include +#include "thread.hpp" + +struct AppMessage; + +extern "C" uint32_t sceAppMessagingSendMsg(uint32_t appId, uint32_t msgType, const void *msg, size_t msgLength, uint32_t flags); + +extern "C" int sceAppMessagingReceiveMsg(const AppMessage *msg); + +struct AppMessage { + static constexpr size_t PAYLOAD_SIZE = 8192; + uint32_t sender; + uint32_t msgType; + uint8_t payload[PAYLOAD_SIZE]; + uint32_t payloadSize; + uint64_t timestamp; +}; + +enum HomebrewDaemonMessageType : uint32_t { + BREW_MSG_TYPE_REGISTER_PREFIX_HANDLER = 0x1000000, + BREW_MSG_TYPE_REGISTER_LAUNCH_LISTENER, + BREW_MSG_TYPE_APP_LAUNCHED +}; + +JThread startMessageReceiver() noexcept; +bool notifyHandlers(const uint32_t prefix, const pid_t pid, const bool isHomebrew) noexcept; +bool hasPrefixHandler(const uint32_t prefix) noexcept; diff --git a/daemon/source/thread.hpp b/daemon/source/thread.hpp index 1a5129f..4b44f95 100644 --- a/daemon/source/thread.hpp +++ b/daemon/source/thread.hpp @@ -86,3 +86,53 @@ class JThread : public Thread { join(); } }; + +class ScopedLock { + friend class Mutex; + + pthread_mutex_t *mtx; + + ScopedLock() = delete; + ScopedLock(pthread_mutex_t *mtx) noexcept : mtx(mtx) { + pthread_mutex_lock(mtx); + } + + public: + ScopedLock(const ScopedLock&) = delete; + ScopedLock &operator=(const ScopedLock&) = delete; + ScopedLock(ScopedLock &&rhs) noexcept : mtx(rhs.mtx) { + rhs.mtx = nullptr; + } + ScopedLock &operator=(ScopedLock &&rhs) noexcept { + if (mtx != nullptr) { + std::terminate(); + } + mtx = rhs.mtx; + rhs.mtx = nullptr; + return *this; + } + ~ScopedLock() noexcept { + if (mtx != nullptr) { + pthread_mutex_unlock(mtx); + } + } +}; + +class Mutex { + pthread_mutex_t mtx; + + public: + Mutex() noexcept : mtx{} { + pthread_mutex_init(&mtx, nullptr); + } + Mutex(const Mutex&) = delete; + Mutex &operator=(const Mutex&) = delete; + Mutex(Mutex &&rhs)= delete; + Mutex &operator=(Mutex &&rhs) = delete; + ~Mutex() noexcept { + pthread_mutex_destroy(&mtx); + } + ScopedLock lock() noexcept { + return &mtx; + } +}; diff --git a/include/kernel/proc.hpp b/include/kernel/proc.hpp index de4b577..4ae19e8 100644 --- a/include/kernel/proc.hpp +++ b/include/kernel/proc.hpp @@ -108,6 +108,7 @@ class KProc : public KernelObject { static constexpr size_t PID_OFFSET = 0xbc; static constexpr size_t THREADS_OFFSET = 0x10; static constexpr size_t FD_OFFSET = 0x48; + static constexpr size_t TITLEID_OFFSET = 0x470; static constexpr size_t SELFINFO_OFFSET = 0x588; static constexpr size_t SELFINFO_NAME_OFFSET = 0x59C; @@ -176,6 +177,11 @@ class KProc : public KernelObject { this->reload(); } } + + String getTitleId() const noexcept { + constexpr auto TITLE_ID_SIZE = 9; + return StringView{reinterpret_cast(buf) + TITLEID_OFFSET, TITLE_ID_SIZE}; + } }; inline KIterator getAllProcs() { diff --git a/include/util.hpp b/include/util.hpp index 7d13caa..77344a6 100644 --- a/include/util.hpp +++ b/include/util.hpp @@ -6,6 +6,9 @@ extern "C" { #include #include #include + void *malloc(size_t length); + void free(void *ptr); + void *realloc(void *ptr, size_t size); } // for things we need but can't have... yet... @@ -250,6 +253,9 @@ class String { void grow(size_t target) { const size_t newCapacity = align(target); + if (capacity >= newCapacity) { + return; + } if (is_sso()) { char *tmp = new char[newCapacity]; __builtin_memcpy(tmp, data.buf, size); @@ -581,6 +587,265 @@ class List { } }; +template +class Vector { + + static constexpr size_t DEFAULT_CAPACITY = 16; + + T *first; + T *last; + T *eos; + + size_t available() const noexcept { + return eos - last; + } + + void grow(size_t cap) noexcept { + if (cap <= capacity()) { + return; + } + first = reallocate(first, cap); + eos = first + cap; + } + + constexpr void setSize(const size_t count, const size_t length, const T &value) noexcept { + if (length > count) { + if constexpr(!__is_trivially_destructible(T)) { + for (size_t i = count; i < length; i++) { + first[i].~T(); + } + } + } else { + grow(count); + for (size_t i = length; i < count; i++) { + first[i] = value; + } + } + last = first + count; + } + + static T *allocate(size_t n) noexcept { + return reinterpret_cast(malloc(n * sizeof(T))); // NOLINT + } + + static T *reallocate(T *ptr, size_t n) noexcept { + // if it fails we're screwed anyway + // no exceptions so we'll just run until fault + return reinterpret_cast(realloc(ptr, n * sizeof(T))); // NOLINT + } + + public: + Vector() noexcept : first(allocate(DEFAULT_CAPACITY)), last(first), eos(first + DEFAULT_CAPACITY) {} // NOLINT + + Vector(const Vector &rhs) noexcept : first(allocate(rhs.capacity())), last(first), eos(first + rhs.capacity()) { // NOLINT + if constexpr(__is_trivially_copyable(T)) { + __builtin_memcpy(first, rhs.first, rhs.size() * sizeof(T)); + } else { + const size_t length = rhs.size(); + for (size_t i = 0; i < length; i++) { + first[i] = rhs[i]; + } + } + } + + Vector &operator=(const Vector &rhs) noexcept { + if (this == &rhs) [[unlikely]] { + return *this; + } + + const size_t length = rhs.size(); + + if (capacity() < length) { + clear(); + } + + first = grow(rhs.capacity()); // NOLINT + last = first + length; + + if constexpr(__is_trivially_copyable(T)) { + __builtin_memcpy(first, rhs.first, length * sizeof(T)); + } else { + for (size_t i = 0; i < length; i++) { + first[i] = rhs[i]; + } + } + + return *this; + } + + Vector(Vector &&rhs) noexcept : first(rhs.first), last(rhs.last), eos(rhs.eos) { + rhs.first = nullptr; + } + + Vector &operator=(Vector &&rhs) noexcept { + free(first); + first = rhs.first; + last = rhs.last; + eos = rhs.eos; + rhs.first = nullptr; + return *this; + } + + ~Vector() noexcept { + free(first); + } + + constexpr T &at(size_t i) noexcept { + return first[i]; + } + + constexpr const T &at(size_t i) const noexcept { + return first[i]; + } + + constexpr T &operator[](size_t i) noexcept { + return first[i]; + } + + constexpr const T &operator[](size_t i) const noexcept { + return first[i]; + } + + constexpr T &front() noexcept { + return *first; + } + + constexpr const T &front() const noexcept { + return *first; + } + + constexpr T &back() noexcept { + return *last; + } + + constexpr const T &back() const noexcept { + return *last; + } + + constexpr T *data() noexcept { + return first; + } + + constexpr const T *data() const noexcept { + return first; + } + + constexpr T *begin() noexcept { + return first; + } + + constexpr const T *begin() const noexcept { + return first; + } + + constexpr const T *cbegin() const noexcept { + return first; + } + + constexpr T *end() noexcept { + return last; + } + + constexpr const T *end() const noexcept { + return last; + } + + constexpr const T *cend() const noexcept { + return last; + } + + constexpr bool empty() const noexcept { + return first == last; + } + + constexpr size_t size() const noexcept { + return last - first; + } + + constexpr void reserve(size_t length) noexcept { + if (length <= capacity()) { + return; + } + grow(length); + } + + constexpr size_t capacity() const noexcept { + return eos - first; + } + + constexpr void shrink_to_fit() noexcept { + if (size() <= capacity()) { + return; + } + first = reallocate(first, size()); + } + + constexpr void clear() noexcept { + if constexpr(!__is_trivially_destructible(T)) { + const size_t length = size(); + for (size_t i = 0; i < length; i++) { + first[i].~T(); + } + } + last = first; + } + + // ok I got lazy + + // + + constexpr T *erase(const T *pos) noexcept { + const size_t i = pos - first; + if constexpr(!__is_trivially_destructible(T)) { + first[i].~T(); + } + if (first + i != --last) { + __builtin_memcpy(last - i, first + i, size() * sizeof(T)); + } + return last; + } + + template + constexpr T &emplace_back(Args&&... args) noexcept { + return *last++ = T{args...}; + } + + constexpr void push_back(const T &value) noexcept { + *last++ = value; + } + + constexpr void push_back(T &&value) noexcept { + *last++ = static_cast(value); + } + + constexpr void pop_back() noexcept { + last--; + if constexpr(!__is_trivially_destructible(T)) { + *last.~T(); + } + } + + constexpr void resize(size_t count) noexcept { + const size_t length = size(); + if (length == count) { + return; + } + setSize(count, length, T()); + } + + constexpr void resize(size_t count, const T &value) noexcept { + const size_t length = size(); + if (length == count) { + return; + } + setSize(count, length, value); + } + + constexpr void swap(Vector &other) noexcept { + swap(*this, other); + } +}; + // NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers) // diff --git a/shellcode/build_cmd.txt b/shellcode/build_cmd.txt index e4c2ba8..ce0313d 100644 --- a/shellcode/build_cmd.txt +++ b/shellcode/build_cmd.txt @@ -1 +1 @@ -clang --target=x86_64-freebsd-pc-elf -fPIC -fPIE -fomit-frame-pointer -Wall -Werror -gfull -gdwarf-2 -O3 -march=znver2 -mavx2 -c +clang --target=x86_64-freebsd-pc-elf -fPIC -fPIE -fomit-frame-pointer -Wall -Werror -gfull -gdwarf-2 -O3 -march=znver2 -mavx2 -c rfork_thread.c -o rfork_thread.o diff --git a/shellcode/rfork_thread.c b/shellcode/rfork_thread.c index fe203a0..ff22b77 100644 --- a/shellcode/rfork_thread.c +++ b/shellcode/rfork_thread.c @@ -15,6 +15,7 @@ #define PONG 1 #define PROCESS_LAUNCHED 1 #define MSG_NOSIGNAL 0x20000 /* do not generate SIGPIPE on EOF */ +#define TITLEID_OFFSET 0xd // NOLINTBEGIN(*) @@ -36,6 +37,7 @@ struct sockaddr_un { typedef struct { int sock; + int daemonPid; const func_t inf_loop; // haha open prospero go brrrrrrr func_t func; int (*socket)(int domain, int type, int protocol); @@ -50,6 +52,7 @@ struct result { int cmd; int pid; func_t func; + unsigned int prefix; }; // INFINITE_LOOP: 0xeb 0xfe @@ -144,9 +147,26 @@ static inline int __attribute__((always_inline)) isHomebrew(ExtraStuff *restrict return stuff->access(path, F_OK) == 0; } +static inline unsigned int __attribute__((always_inline)) getTitleId(procSpawnArgs *restrict arg) { + return *(unsigned int *)(arg->sandboxPath + TITLEID_OFFSET); +} + static int __attribute__((used)) rfork_thread_hook(int flags, void *stack, func_t func, procSpawnArgs *restrict arg, rfork_thread_t orig, ExtraStuff *restrict stuff) { if (!isHomebrew(stuff, arg)) { - return orig(flags, stack, func, arg); + const int pid = orig(flags, stack, func, arg); + if (stuff->sock == -1) { + // too bad + return pid; + } + + struct result res = { + .cmd = PROCESS_LAUNCHED, + .pid = pid, + .func = 0, + .prefix = getTitleId(arg) + }; + stuff->send(stuff->sock, (void *)&res, sizeof(res), MSG_NOSIGNAL); + return pid; } volatile unsigned long ipc[2]; @@ -182,7 +202,8 @@ static int __attribute__((used)) rfork_thread_hook(int flags, void *stack, func_ struct result res = { .cmd = PROCESS_LAUNCHED, .pid = pid, - .func = func + .func = func, + .prefix = getTitleId(arg) }; // we must always write a response so the daemon doesn't get stuck diff --git a/spawner/source/main.cpp b/spawner/source/main.cpp index 5e37d76..2a790dc 100644 --- a/spawner/source/main.cpp +++ b/spawner/source/main.cpp @@ -225,7 +225,7 @@ struct HookBuilder { // NOLINTBEGIN(*) struct ShellcodeBuilder { - static constexpr size_t SHELLCODE_SIZE = 663; + static constexpr size_t SHELLCODE_SIZE = 748; static constexpr size_t RFORK_THREAD_ADDR_OFFSET = 2; static constexpr size_t EXTRA_STUFF_ADDR_OFFSET = 12; @@ -240,52 +240,55 @@ struct ShellcodeBuilder { } }; -// insert 0x48, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - static constexpr ShellcodeBuilder BUILDER_TEMPLATE{{ 0x49, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV rfork_thread, R8 0x49, 0xb9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // MOV &stuff, R9 - 0x55, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x53, 0x48, 0x81, 0xec, 0xa8, 0x00, 0x00, - 0x00, 0x49, 0x89, 0xce, 0x49, 0x89, 0xd7, 0x49, 0x89, 0xf4, 0x89, 0xfd, 0x48, 0x85, 0xc9, 0x0f, - 0x84, 0xc9, 0x00, 0x00, 0x00, 0x49, 0x8b, 0x4e, 0x08, 0x48, 0x85, 0xc9, 0x0f, 0x84, 0xbc, 0x00, - 0x00, 0x00, 0x49, 0x8b, 0x46, 0x10, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xaf, 0x00, 0x00, 0x00, 0x48, - 0xbe, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x48, 0xba, 0x65, 0x78, 0x2f, 0x61, 0x70, - 0x70, 0x2f, 0x42, 0x48, 0xbf, 0x52, 0x45, 0x57, 0x30, 0x30, 0x30, 0x30, 0x30, 0x4d, 0x89, 0xcd, - 0x48, 0x89, 0x74, 0x24, 0x20, 0x48, 0x89, 0x54, 0x24, 0x28, 0x48, 0x89, 0x7c, 0x24, 0x30, 0xc5, - 0xf9, 0x6f, 0x44, 0x24, 0x20, 0xc5, 0xfa, 0x7e, 0x4c, 0x24, 0x30, 0xc5, 0xfa, 0x7e, 0x51, 0x10, - 0xc5, 0xf9, 0xef, 0x01, 0xc5, 0xf1, 0xef, 0xca, 0xc5, 0xf1, 0xeb, 0xc0, 0xc4, 0xe2, 0x79, 0x17, - 0xc0, 0x74, 0x7f, 0xc5, 0xfa, 0x6f, 0x00, 0xc5, 0xfa, 0x6f, 0x48, 0x0a, 0x48, 0xb8, 0x2f, 0x61, - 0x70, 0x70, 0x30, 0x2f, 0x68, 0x6f, 0x48, 0x8d, 0x7c, 0x24, 0x20, 0x31, 0xf6, 0x4c, 0x89, 0xc3, - 0xc5, 0xfa, 0x7f, 0x4c, 0x24, 0x2a, 0xc5, 0xf9, 0x7f, 0x44, 0x24, 0x20, 0x48, 0x89, 0x44, 0x24, - 0x3a, 0x48, 0xb8, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x2e, 0x65, 0x48, 0x89, 0x44, 0x24, 0x42, - 0x48, 0xc7, 0x44, 0x24, 0x4a, 0x6c, 0x66, 0x00, 0x00, 0x41, 0xff, 0x55, 0x40, 0x48, 0xbe, 0x2f, - 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x49, 0x89, 0xd8, 0x85, 0xc0, 0x74, 0x24, 0x89, 0xef, - 0x4c, 0x89, 0xe6, 0x4c, 0x89, 0xfa, 0x4c, 0x89, 0xf1, 0x41, 0xff, 0xd0, 0x89, 0xc3, 0x89, 0xd8, - 0x48, 0x81, 0xc4, 0xa8, 0x00, 0x00, 0x00, 0x5b, 0x41, 0x5c, 0x41, 0x5d, 0x41, 0x5e, 0x41, 0x5f, - 0x5d, 0xc3, 0x48, 0xb8, 0x74, 0x6d, 0x70, 0x2f, 0x49, 0x50, 0x43, 0x00, 0x4c, 0x89, 0x44, 0x24, - 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x44, 0x24, 0x18, 0x41, 0x8b, 0x5d, 0x00, 0x83, - 0xfb, 0xff, 0x74, 0x71, 0x48, 0x8d, 0xb4, 0x24, 0x98, 0x00, 0x00, 0x00, 0x89, 0xdf, 0xba, 0x10, - 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x02, 0x00, 0xc7, 0x84, 0x24, 0x98, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x48, 0xc7, 0x84, 0x24, 0xa0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc7, - 0x84, 0x24, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xff, 0x55, 0x30, 0x48, 0x83, - 0xf8, 0xff, 0x74, 0x4f, 0x48, 0x8d, 0x74, 0x24, 0x20, 0x89, 0xdf, 0xba, 0x04, 0x00, 0x00, 0x00, - 0xb9, 0x00, 0x00, 0x02, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0x41, 0xff, 0x55, - 0x38, 0x48, 0x83, 0xf8, 0xff, 0x74, 0x07, 0x83, 0x7c, 0x24, 0x20, 0x01, 0x74, 0x77, 0x89, 0xdf, - 0xe9, 0xbe, 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x31, - 0xd2, 0x41, 0xff, 0x55, 0x18, 0x41, 0x89, 0x45, 0x00, 0x83, 0xf8, 0xff, 0x75, 0x22, 0xe9, 0xac, - 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, 0x00, 0x31, 0xd2, 0x41, - 0xff, 0x55, 0x18, 0x41, 0x89, 0x45, 0x00, 0x83, 0xf8, 0xff, 0x0f, 0x84, 0x87, 0x00, 0x00, 0x00, - 0xc6, 0x44, 0x24, 0x20, 0x00, 0xc6, 0x44, 0x24, 0x21, 0x01, 0x89, 0xc3, 0x48, 0x8d, 0x74, 0x24, - 0x20, 0xba, 0x11, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x44, 0x24, 0x10, 0x89, 0xdf, 0x48, 0x89, 0x44, - 0x24, 0x22, 0x48, 0x8b, 0x44, 0x24, 0x18, 0x48, 0x89, 0x44, 0x24, 0x2a, 0x41, 0xff, 0x55, 0x28, - 0x83, 0xf8, 0xff, 0x74, 0x89, 0x48, 0x8b, 0x44, 0x24, 0x08, 0x49, 0x8b, 0x55, 0x08, 0x89, 0xef, - 0x4c, 0x89, 0xe6, 0x4c, 0x89, 0xf1, 0x89, 0x5c, 0x24, 0x04, 0xff, 0xd0, 0x8b, 0x7c, 0x24, 0x04, - 0x48, 0x8d, 0x74, 0x24, 0x20, 0xba, 0x10, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x02, 0x00, 0xc7, - 0x44, 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x24, 0x89, 0xc3, 0x4c, 0x89, 0x7c, - 0x24, 0x28, 0x41, 0xff, 0x55, 0x30, 0x83, 0xfb, 0xff, 0x0f, 0x85, 0x9f, 0xfe, 0xff, 0xff, 0x8b, - 0x7c, 0x24, 0x04, 0x41, 0xff, 0x55, 0x20, 0x41, 0xc7, 0x45, 0x00, 0xff, 0xff, 0xff, 0xff, 0x89, - 0xef, 0x4c, 0x89, 0xe6, 0x4c, 0x89, 0xfa, 0x4c, 0x89, 0xf1, 0xff, 0x54, 0x24, 0x08, 0xe9, 0x79, - 0xfe, 0xff, 0xff + 0x55, 0x41, 0x57, 0x41, 0x56, 0x41, 0x55, 0x41, 0x54, 0x53, 0x48, 0x81, 0xec, 0xa8, 0x00, 0x00, + 0x00, 0x4d, 0x89, 0xcf, 0x48, 0x89, 0xcb, 0x49, 0x89, 0xd4, 0x49, 0x89, 0xf5, 0x89, 0xfd, 0x48, + 0x85, 0xc9, 0x0f, 0x84, 0xca, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x4b, 0x08, 0x48, 0x85, 0xc9, 0x0f, + 0x84, 0xbd, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x43, 0x10, 0x48, 0x85, 0xc0, 0x0f, 0x84, 0xb0, 0x00, + 0x00, 0x00, 0x48, 0xbe, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x48, 0xba, 0x65, 0x78, + 0x2f, 0x61, 0x70, 0x70, 0x2f, 0x42, 0x48, 0xbf, 0x52, 0x45, 0x57, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x48, 0x89, 0x74, 0x24, 0x20, 0x48, 0x89, 0x54, 0x24, 0x28, 0x48, 0x89, 0x7c, 0x24, 0x30, 0xc5, + 0xf9, 0x6f, 0x44, 0x24, 0x20, 0xc5, 0xfa, 0x7e, 0x4c, 0x24, 0x30, 0xc5, 0xfa, 0x7e, 0x51, 0x10, + 0xc5, 0xf9, 0xef, 0x01, 0xc5, 0xf1, 0xef, 0xca, 0xc5, 0xf1, 0xeb, 0xc0, 0xc4, 0xe2, 0x79, 0x17, + 0xc0, 0x0f, 0x84, 0xbd, 0x00, 0x00, 0x00, 0xc5, 0xfa, 0x6f, 0x00, 0xc5, 0xfa, 0x6f, 0x48, 0x0a, + 0x48, 0xb8, 0x2f, 0x61, 0x70, 0x70, 0x30, 0x2f, 0x68, 0x6f, 0x48, 0x8d, 0x7c, 0x24, 0x20, 0x31, + 0xf6, 0x4d, 0x89, 0xc6, 0xc5, 0xfa, 0x7f, 0x4c, 0x24, 0x2a, 0xc5, 0xf9, 0x7f, 0x44, 0x24, 0x20, + 0x48, 0x89, 0x44, 0x24, 0x3a, 0x48, 0xb8, 0x6d, 0x65, 0x62, 0x72, 0x65, 0x77, 0x2e, 0x65, 0x48, + 0x89, 0x44, 0x24, 0x42, 0x48, 0xc7, 0x44, 0x24, 0x4a, 0x6c, 0x66, 0x00, 0x00, 0x41, 0xff, 0x57, + 0x40, 0x48, 0xbe, 0x2f, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x5f, 0x4d, 0x89, 0xf0, 0x85, 0xc0, + 0x74, 0x62, 0x89, 0xef, 0x4c, 0x89, 0xee, 0x4c, 0x89, 0xe2, 0x48, 0x89, 0xd9, 0x41, 0xff, 0xd0, + 0x41, 0x8b, 0x3f, 0x41, 0x89, 0xc6, 0x83, 0xff, 0xff, 0x74, 0x34, 0x48, 0x8b, 0x43, 0x10, 0xc7, + 0x44, 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0x44, 0x89, 0x74, 0x24, 0x24, 0x48, 0xc7, 0x44, 0x24, + 0x28, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x74, 0x24, 0x20, 0xba, 0x18, 0x00, 0x00, 0x00, 0xb9, + 0x00, 0x00, 0x02, 0x00, 0x8b, 0x40, 0x0d, 0x89, 0x44, 0x24, 0x30, 0x41, 0xff, 0x57, 0x30, 0x44, + 0x89, 0xf0, 0x48, 0x81, 0xc4, 0xa8, 0x00, 0x00, 0x00, 0x5b, 0x41, 0x5c, 0x41, 0x5d, 0x41, 0x5e, + 0x41, 0x5f, 0x5d, 0xc3, 0x48, 0xb8, 0x74, 0x6d, 0x70, 0x2f, 0x49, 0x50, 0x43, 0x00, 0x4c, 0x89, + 0x44, 0x24, 0x08, 0x48, 0x89, 0x74, 0x24, 0x10, 0x48, 0x89, 0x44, 0x24, 0x18, 0x45, 0x8b, 0x37, + 0x41, 0x83, 0xfe, 0xff, 0x74, 0x74, 0x48, 0x8d, 0xb4, 0x24, 0x90, 0x00, 0x00, 0x00, 0x44, 0x89, + 0xf7, 0xba, 0x18, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x02, 0x00, 0xc7, 0x84, 0x24, 0x90, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0xc7, 0x84, 0x24, 0x98, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0xc7, 0x84, 0x24, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xff, 0x57, + 0x30, 0x48, 0x83, 0xf8, 0xff, 0x74, 0x50, 0x48, 0x8d, 0x74, 0x24, 0x20, 0x44, 0x89, 0xf7, 0xba, + 0x04, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x02, 0x00, 0xc7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, + 0x00, 0x41, 0xff, 0x57, 0x38, 0x48, 0x83, 0xf8, 0xff, 0x74, 0x07, 0x83, 0x7c, 0x24, 0x20, 0x01, + 0x74, 0x78, 0x44, 0x89, 0xf7, 0xe9, 0xcc, 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xbe, + 0x01, 0x00, 0x00, 0x00, 0x31, 0xd2, 0x41, 0xff, 0x57, 0x18, 0x41, 0x89, 0x07, 0x83, 0xf8, 0xff, + 0x75, 0x21, 0xe9, 0xba, 0x00, 0x00, 0x00, 0xbf, 0x01, 0x00, 0x00, 0x00, 0xbe, 0x01, 0x00, 0x00, + 0x00, 0x31, 0xd2, 0x41, 0xff, 0x57, 0x18, 0x41, 0x89, 0x07, 0x83, 0xf8, 0xff, 0x0f, 0x84, 0x97, + 0x00, 0x00, 0x00, 0xc6, 0x44, 0x24, 0x20, 0x00, 0xc6, 0x44, 0x24, 0x21, 0x01, 0x41, 0x89, 0xc6, + 0x48, 0x8d, 0x74, 0x24, 0x20, 0xba, 0x11, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x44, 0x24, 0x10, 0x44, + 0x89, 0xf7, 0x48, 0x89, 0x44, 0x24, 0x22, 0x48, 0x8b, 0x44, 0x24, 0x18, 0x48, 0x89, 0x44, 0x24, + 0x2a, 0x41, 0xff, 0x57, 0x28, 0x83, 0xf8, 0xff, 0x74, 0x88, 0x48, 0x8b, 0x44, 0x24, 0x08, 0x49, + 0x8b, 0x57, 0x08, 0x89, 0xef, 0x4c, 0x89, 0xee, 0x48, 0x89, 0xd9, 0x44, 0x89, 0x74, 0x24, 0x04, + 0xff, 0xd0, 0xc7, 0x44, 0x24, 0x20, 0x01, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x24, 0x41, 0x89, + 0xc6, 0x48, 0x8b, 0x43, 0x10, 0x4c, 0x89, 0x64, 0x24, 0x28, 0x8b, 0x7c, 0x24, 0x04, 0x48, 0x8d, + 0x74, 0x24, 0x20, 0xba, 0x18, 0x00, 0x00, 0x00, 0xb9, 0x00, 0x00, 0x02, 0x00, 0x8b, 0x40, 0x0d, + 0x89, 0x44, 0x24, 0x30, 0x41, 0xff, 0x57, 0x30, 0x41, 0x83, 0xfe, 0xff, 0x0f, 0x85, 0x8d, 0xfe, + 0xff, 0xff, 0x8b, 0x7c, 0x24, 0x04, 0x41, 0xff, 0x57, 0x20, 0x41, 0xc7, 0x07, 0xff, 0xff, 0xff, + 0xff, 0x89, 0xef, 0x4c, 0x89, 0xee, 0x4c, 0x89, 0xe2, 0x48, 0x89, 0xd9, 0xff, 0x54, 0x24, 0x08, + 0x41, 0x89, 0xc6, 0xe9, 0x67, 0xfe, 0xff, 0xff }}; static const uint8_t INFINITE_LOOP[]{0xeb, 0xfe}; @@ -365,13 +368,13 @@ UniquePtr patchSyscore() { extern "C" int sceUserServiceGetForegroundUser(uint32_t *userId); enum Flag : uint64_t { - Flag_None = 0, - SkipLaunchCheck = 1, - SkipResumeCheck = 1, - SkipSystemUpdateCheck = 2, - RebootPatchInstall = 4, - VRMode = 8, - NonVRMode = 16, + Flag_None = 0, + SkipLaunchCheck = 1, + SkipResumeCheck = 1, + SkipSystemUpdateCheck = 2, + RebootPatchInstall = 4, + VRMode = 8, + NonVRMode = 16, Pft = 32UL, RaIsConfirmed = 64UL, ShellUICheck = 128UL @@ -379,11 +382,11 @@ enum Flag : uint64_t { struct LncAppParam { - uint32_t sz; - uint32_t user_id; - uint32_t app_opt; - uint64_t crash_report; - Flag check_flag; + uint32_t sz; + uint32_t user_id; + uint32_t app_opt; + uint64_t crash_report; + Flag check_flag; }; extern "C" int sceKernelLoadStartModule(const char *name, size_t argc, const void *argv, uint32_t flags, void *unknown, int *result); @@ -611,7 +614,7 @@ int networkListen(const char* soc_path) { } printf("touching %s\n", "/system_tmp/IPC"); - touch_file("/system_tmp/IPC"); + touch_file("/system_tmp/IPC"); printf("network listen unix socket %d\n", s); return s; } @@ -715,6 +718,7 @@ static void *hookThread(void *args) noexcept { puts("execve completed"); while (helper->spawned == nullptr) { + usleep(100); // NOLINT helper->spawned = Hijacker::getHijacker(pid); }