Skip to content

Commit

Permalink
Make code more robust.
Browse files Browse the repository at this point in the history
Added Injector and Fixed crashes on Linux
Use same injector on all platforms.
  • Loading branch information
Brandon-T committed Nov 5, 2024
1 parent 6628dc7 commit 737b1d3
Show file tree
Hide file tree
Showing 37 changed files with 7,243 additions and 112 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ IF(WIN32)
set(EXTRA_LIBRARIES
user32
opengl32
gdi32)
gdi32
dbghelp) # Needed for ThirdParty/kubo/injector
ELSEIF(APPLE)
find_library(FOUNDATION Foundation)
find_library(COCOA Cocoa)
Expand Down
2 changes: 0 additions & 2 deletions RemoteInput/Injection/Injector.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@
#ifndef REMOTEINPUT_INJECTOR_HXX
#define REMOTEINPUT_INJECTOR_HXX

#include <utility>
#include <cstdint>
#include <string>
#include <sys/types.h>

class Injector
{
Expand Down
3 changes: 3 additions & 0 deletions RemoteInput/Injection/Injector_Arm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -419,6 +419,9 @@ bool Injector::Inject(std::string module_path, std::int32_t pid, void* bootstrap
ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
return false;
}

ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
return true;
}

ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
Expand Down
1 change: 1 addition & 0 deletions RemoteInput/Injection/Injector_Darwin.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#if defined(__APPLE__)
#include <dlfcn.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <mach/mach.h>
#include <mach/mach_vm.h>
#include <mach-o/loader.h>
Expand Down
3 changes: 3 additions & 0 deletions RemoteInput/Injection/Injector_Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,9 @@ bool Injector::Inject(std::string module_path, std::int32_t pid, void* bootstrap
ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
return false;
}

ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
return true;
}

ptrace(PTRACE_DETACH, pid, nullptr, nullptr);
Expand Down
3 changes: 1 addition & 2 deletions RemoteInput/JVM.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,14 @@ JVM::JVM() noexcept : vm(nullptr), createdVM(false), loadedJNI(false), module(nu
}
#endif

this->createdVM = false;
jint num_vms = 0;
const jint max_vms = 1;
JavaVM* vms[max_vms] = {0};
if (this->JNI_GetCreatedJavaVMs(vms, max_vms, &num_vms) == JNI_OK)
{
for (int i = 0; i < num_vms; ++i)
{
if (vms[i] != NULL)
if (vms[i] != nullptr)
{
this->vm = vms[i];
break;
Expand Down
107 changes: 75 additions & 32 deletions RemoteInput/Platform/Platform_Darwin.mm
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,24 @@
#endif

#include <Thirdparty/Hook.hxx>
#include <Injection/Injector.hxx>
#if defined(CUSTOM_INJECTOR)
#include "Injection/Injector.hxx"
#else
#include "Thirdparty/Injector.hxx"
#endif
#include <signal.h>
#include <libproc.h>
#include <sys/syscall.h>
#include <mach-o/dyld.h>
#include <filesystem>
#endif // defined

#if defined(__APPLE__)
std::string StripPath(const std::string& path_to_strip)
{
return std::filesystem::path(path_to_strip).filename().string();
}

void GetDesktopResolution(int &width, int &height) noexcept
{
auto get_screen_resolution = [&]{
Expand Down Expand Up @@ -117,10 +127,35 @@ bool IsThreadAlive(std::int32_t tid) noexcept
std::string path = std::string(PATH_MAX, '\0');
if (realpath(info.dli_fname, &path[0]))
{
if (Injector::Inject(info.dli_fname, pid, nullptr))
#if defined(CUSTOM_INJECTOR)
if (Injector::Inject(path.c_str(), pid, nullptr))
{
return pid;
}
#else
extern std::vector<std::unique_ptr<Injector>> injectors;

for (auto& injector : injectors)
{
if (injector && injector->get_pid() == pid)
{
if (injector->is_injected())
{
return pid;
}

return injector->Inject(path.c_str()) ? pid : -1;
}
}

std::unique_ptr<Injector> injector = std::make_unique<Injector>(pid);
if (injector)
{
bool result = injector->Inject(path.c_str());
injectors.push_back(std::move(injector));
return result ? pid : -1;
}
#endif
}
}
return -1;
Expand Down Expand Up @@ -163,9 +198,13 @@ bool IsThreadAlive(std::int32_t tid) noexcept
for (std::uint32_t i = 0; i < count; ++i)
{
const char* name = _dyld_get_image_name(i);
if (!strcasestr(name, partial_module_name))
if (name)
{
result.push_back(name);
std::string module_name = StripPath(name);
if (!strcasestr(module_name.c_str(), partial_module_name))
{
result.push_back(name);
}
}
}

Expand All @@ -178,43 +217,47 @@ bool IsThreadAlive(std::int32_t tid) noexcept
for (std::uint32_t i = 0; i < count; ++i)
{
const char* name = _dyld_get_image_name(i);
if (strcasestr(name, module_name))
if (name)
{
return dlopen(name, RTLD_NOLOAD);

/*const struct mach_header* header = _dyld_get_image_header(i);
//std::intptr_t offset = _dyld_get_image_vmaddr_slide(i);
const struct load_command* cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char *>(header) + sizeof(struct mach_header));
if (header->magic == MH_MAGIC_64)
std::string stripped_name = StripPath(name);
if (strcasestr(stripped_name.c_str(), module_name))
{
cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char *>(header) + sizeof(struct mach_header_64));
}
return dlopen(name, RTLD_NOLOAD);

for (std::uint32_t j = 0; j < header->ncmds; ++j)
{
if (cmd->cmd == LC_SEGMENT)
{
const struct segment_command* seg = reinterpret_cast<const struct segment_command*>(cmd);
void* base_addr = reinterpret_cast<void*>(seg->vmaddr); //seg->vmaddr + offset;
/*const struct mach_header* header = _dyld_get_image_header(i);
//std::intptr_t offset = _dyld_get_image_vmaddr_slide(i);
Dl_info info = {0};
dladdr(base_addr, &info);
return dlopen(info.dli_fname, RTLD_NOLOAD);
const struct load_command* cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char *>(header) + sizeof(struct mach_header));
if (header->magic == MH_MAGIC_64)
{
cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char *>(header) + sizeof(struct mach_header_64));
}
if (cmd->cmd == LC_SEGMENT_64)
for (std::uint32_t j = 0; j < header->ncmds; ++j)
{
const struct segment_command_64* seg = reinterpret_cast<const struct segment_command_64*>(cmd);
void* base_addr = reinterpret_cast<void*>(seg->vmaddr); //seg->vmaddr + offset;
if (cmd->cmd == LC_SEGMENT)
{
const struct segment_command* seg = reinterpret_cast<const struct segment_command*>(cmd);
void* base_addr = reinterpret_cast<void*>(seg->vmaddr); //seg->vmaddr + offset;
Dl_info info = {0};
dladdr(base_addr, &info);
return dlopen(info.dli_fname, RTLD_NOLOAD);
}
Dl_info info = {0};
dladdr(base_addr, &info);
return dlopen(info.dli_fname, RTLD_NOLOAD);
}
if (cmd->cmd == LC_SEGMENT_64)
{
const struct segment_command_64* seg = reinterpret_cast<const struct segment_command_64*>(cmd);
void* base_addr = reinterpret_cast<void*>(seg->vmaddr); //seg->vmaddr + offset;
Dl_info info = {0};
dladdr(base_addr, &info);
return dlopen(info.dli_fname, RTLD_NOLOAD);
}
cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char*>(cmd) + cmd->cmdsize);
}*/
cmd = reinterpret_cast<const struct load_command*>(reinterpret_cast<const char*>(cmd) + cmd->cmdsize);
}*/
}
}
}
return dlopen(module_name, RTLD_NOLOAD);
Expand Down
99 changes: 46 additions & 53 deletions RemoteInput/Platform/Platform_Linux.cxx
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include "Platform.hxx"

#if defined(__linux__)
#if defined(CUSTOM_INJECTOR)
#include "Injection/Injector.hxx"
#else
#include "Thirdparty/Injector.hxx"
#endif

#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/Xutil.h>
Expand All @@ -23,9 +28,15 @@
#include <cstring>
#include <vector>
#include <algorithm>
#include <filesystem>
#endif // defined

#if defined(__linux__)
std::string StripPath(const std::string& path_to_strip)
{
return std::filesystem::path(path_to_strip).filename().string();
}

void GetDesktopResolution(int &width, int &height) noexcept
{
Display* display = XOpenDisplay(nullptr);
Expand Down Expand Up @@ -191,10 +202,35 @@ std::int32_t InjectProcess(std::int32_t pid) noexcept
std::string path = std::string(PATH_MAX, '\0');
if (realpath(info.dli_fname, &path[0]))
{
if (Injector::Inject(info.dli_fname, pid, nullptr))
#if defined(CUSTOM_INJECTOR)
if (Injector::Inject(path.c_str(), pid, nullptr))
{
return pid;
}
#else
extern std::vector<std::unique_ptr<Injector>> injectors;

for (auto& injector : injectors)
{
if (injector && injector->get_pid() == pid)
{
if (injector->is_injected())
{
return pid;
}

return injector->Inject(path.c_str()) ? pid : -1;
}
}

std::unique_ptr<Injector> injector = std::make_unique<Injector>(pid);
if (injector)
{
bool result = injector->Inject(path.c_str());
injectors.push_back(std::move(injector));
return result ? pid : -1;
}
#endif
}
}
return -1;
Expand Down Expand Up @@ -419,10 +455,10 @@ std::vector<std::string> GetLoadedModuleNames(const char* partial_module_name) n
if (info && info->dlpi_name)
{
Module* module_info = static_cast<Module*>(data);
if (strcasestr(info->dlpi_name, module_info->module_name))
std::string module_name = StripPath(info->dlpi_name);
if (strcasestr(module_name.c_str(), module_info->module_name))
{
module_info->result.push_back(info->dlpi_name);
return 1;
}
}
return 0;
Expand All @@ -441,15 +477,16 @@ void* GetModuleHandle(const char* module_name) noexcept
if (info && info->dlpi_name)
{
Module* module_info = static_cast<Module*>(data);
if (strcasestr(info->dlpi_name, module_info->module_name))
std::string module_name = StripPath(info->dlpi_name);
if (strcasestr(module_name.c_str(), module_info->module_name))
{
module_info->result = dlopen(module_info->module_name, RTLD_NOLOAD);
return 1;
return module_info->result ? 1 : 0;
}
}
return 0;
}, reinterpret_cast<void*>(&module_info));
return module_info.result ?: dlopen(module_name, RTLD_NOLOAD);
}, &module_info);
return module_info.result ? module_info.result : dlopen(module_name, RTLD_NOLOAD);
}
#endif

Expand Down Expand Up @@ -551,50 +588,6 @@ std::unique_ptr<Reflection> GetNativeReflector() noexcept
{
std::unique_ptr<Reflection> reflection;
bool hasReflection = TimeOut(20, [&]{
jclass cls = env->FindClass("java/awt/Frame");
if (!cls)
{
return false;
}

jmethodID method = env->GetStaticMethodID(cls, "getFrames", "()[Ljava/awt/Frame;");
if (!method)
{
return false;
}

jobjectArray frames = static_cast<jobjectArray>(env->CallStaticObjectMethod(cls, method));
env->DeleteLocalRef(cls);
if (!frames)
{
return false;
}

jsize size = env->GetArrayLength(frames);
for (jsize i = 0; i < size; ++i)
{
jobject frame = env->GetObjectArrayElement(frames, i);
if (frame)
{
if (IsValidFrame(env, frame))
{
reflection = Reflection::Create(frame);
if (reflection)
{
env->DeleteLocalRef(frames);
return true;
}
}

env->DeleteLocalRef(frame);
}
}

env->DeleteLocalRef(frames);
return false;
});

bool hasReflection2 = !hasReflection && TimeOut(20, [&]{
if (!ModuleLoaded("libawt_xawt.so"))
{
return false;
Expand All @@ -610,7 +603,7 @@ std::unique_ptr<Reflection> GetNativeReflector() noexcept
void* windowFrame = reinterpret_cast<void*>(GetMainWindow());
if (windowFrame)
{
jobject frame = awt_GetComponent(reflection->getEnv(), windowFrame); //java.awt.Frame
jobject frame = awt_GetComponent(env, windowFrame); //java.awt.Frame
if (frame)
{
if (IsValidFrame(env, frame))
Expand All @@ -627,7 +620,7 @@ std::unique_ptr<Reflection> GetNativeReflector() noexcept
});
});

if (hasReflection || hasReflection2)
if (hasReflection)
{
return reflection;
}
Expand Down
Loading

0 comments on commit 737b1d3

Please sign in to comment.