Skip to content

Commit

Permalink
chore!: Detect process bitness
Browse files Browse the repository at this point in the history
  • Loading branch information
cyperdark committed Oct 23, 2024
1 parent bc99ba5 commit 90881ef
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 18 deletions.
7 changes: 5 additions & 2 deletions packages/tosu/src/instances/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Process } from 'tsprocess/dist/process';
import { AbstractInstance } from '@/instances';

import { LazerInstance } from './lazerInstance';
import { OsuInstance } from './osuInstance';

export class InstanceManager {
osuInstances: {
Expand Down Expand Up @@ -48,7 +49,9 @@ export class InstanceManager {
continue;
}

const osuInstance = new LazerInstance(processId);
const osuInstance = Process.isProcess64bit(processId)
? new LazerInstance(processId)
: new OsuInstance(processId);
const cmdLine = osuInstance.process.getProcessCommandLine();

const args = argumetsParser(cmdLine);
Expand Down Expand Up @@ -83,6 +86,6 @@ export class InstanceManager {
runWatcher() {
this.handleProcesses();

setTimeout(this.runWatcher, 5000);
setTimeout(this.runWatcher, 1000);
}
}
82 changes: 75 additions & 7 deletions packages/tsprocess/lib/functions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,15 @@ Napi::Value read_byte(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<int8_t>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read byte at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -33,7 +41,15 @@ Napi::Value read_short(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<int16_t>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read short at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -50,7 +66,15 @@ Napi::Value read_int(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<int32_t>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read int at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -67,7 +91,15 @@ Napi::Value read_uint(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<uint32_t>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read uint at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -84,7 +116,15 @@ Napi::Value read_float(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<float>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read float at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -101,7 +141,15 @@ Napi::Value read_long(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<int64_t>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read long at %x", address)).ThrowAsJavaScriptException();
Expand All @@ -118,7 +166,15 @@ Napi::Value read_double(const Napi::CallbackInfo &args) {
}

auto handle = reinterpret_cast<void *>(args[0].As<Napi::Number>().Int64Value());
auto address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
auto bitness = args[2].As<Napi::Number>().Int32Value();
intptr_t address;

if (bitness == 64) {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Int64Value());
} else {
address = static_cast<intptr_t>(args[1].As<Napi::Number>().Uint32Value());
}

auto result = memory::read<double>(handle, address);
if (!std::get<1>(result)) {
Napi::TypeError::New(env, logger::format("Couldn't read double at %x", address)).ThrowAsJavaScriptException();
Expand Down Expand Up @@ -309,6 +365,17 @@ Napi::Value is_process_exist(const Napi::CallbackInfo &args) {
return Napi::Boolean::New(env, memory::is_process_exist(handle));
}

Napi::Value is_process_64bit(const Napi::CallbackInfo &args) {
Napi::Env env = args.Env();
if (args.Length() < 1) {
Napi::TypeError::New(env, "Wrong number of arguments").ThrowAsJavaScriptException();
return env.Null();
}

auto process_id = args[0].As<Napi::Number>().Int64Value();
return Napi::Boolean::New(env, memory::is_process_64bit(process_id));
}

Napi::Value get_process_path(const Napi::CallbackInfo &args) {
Napi::Env env = args.Env();
if (args.Length() < 1) {
Expand Down Expand Up @@ -460,6 +527,7 @@ Napi::Object init(Napi::Env env, Napi::Object exports) {
exports["openProcess"] = Napi::Function::New(env, open_process);
exports["findProcesses"] = Napi::Function::New(env, find_processes);
exports["isProcessExist"] = Napi::Function::New(env, is_process_exist);
exports["isProcess64bit"] = Napi::Function::New(env, is_process_64bit);
exports["getProcessPath"] = Napi::Function::New(env, get_process_path);
exports["getProcessCommandLine"] = Napi::Function::New(env, get_process_command_line);
exports["getProcessCwd"] = Napi::Function::New(env, get_process_cwd);
Expand Down
1 change: 1 addition & 0 deletions packages/tsprocess/lib/memory/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ std::vector<MemoryRegion> query_regions(void *process);
std::vector<uint32_t> find_processes(const std::string_view process_name);

void *open_process(uint32_t id);
bool is_process_64bit(uint32_t id);
bool is_process_exist(void *process);
std::string get_process_path(void *process);
std::string get_process_command_line(void *process);
Expand Down
21 changes: 21 additions & 0 deletions packages/tsprocess/lib/memory/memory_linux.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,27 @@ bool memory::is_process_exist(void *process) {
return true;
}

bool memory::is_process_64bit(uint32_t id) {
const auto exe_path = "/proc/" + std::to_string(id) + "/exe";

std::ifstream file(exe_path, std::ios::binary);
if (!file.is_open()) {
return false;
}

unsigned char magic[4];
file.read(reinterpret_cast<char*>(magic), sizeof(magic));

if (magic[0] != 0x7F || magic[1] != 'E' || magic[2] != 'L' || magic[3] != 'F') {
return false;
}

unsigned char elf_class;
file.read(reinterpret_cast<char*>(&elf_class), sizeof(elf_class));

return elf_class == 2;
}

std::string memory::get_process_path(void *process) {
const auto pid = reinterpret_cast<uintptr_t>(process);
const auto path = "/proc/" + std::to_string(pid) + "/exe";
Expand Down
13 changes: 13 additions & 0 deletions packages/tsprocess/lib/memory/memory_windows.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ bool memory::is_process_exist(void *handle) {
return false;
}

bool memory::is_process_64bit(uint32_t id) {
HANDLE process_handle = OpenProcess(PROCESS_VM_READ | PROCESS_QUERY_INFORMATION, FALSE, id);
BOOL is_wow64 = FALSE;

if (!IsWow64Process(process_handle, &is_wow64)) {
DWORD error = GetLastError();
std::cerr << "Failed to determine process bitness, error: " << error << std::endl;
return false;
}

return !is_wow64;
}

std::string memory::get_process_path(void *handle) {
char filePath[MAX_PATH];
GetModuleFileNameExA(handle, NULL, filePath, MAX_PATH);
Expand Down
22 changes: 13 additions & 9 deletions packages/tsprocess/src/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ export class Process {
return ProcessUtils.isProcessExist(pid);
}

static isProcess64bit(pid: number): boolean {
return ProcessUtils.isProcess64bit(pid);
}

static disablePowerThrottling() {
return ProcessUtils.disablePowerThrottling();
}
Expand Down Expand Up @@ -79,40 +83,40 @@ export class Process {

readIntPtr(address: number): number {
return this.bitness === 64
? ProcessUtils.readLong(this.handle, address)
: ProcessUtils.readInt(this.handle, address);
? ProcessUtils.readLong(this.handle, address, this.bitness)
: ProcessUtils.readInt(this.handle, address, this.bitness);
}

readByte(address: number): number {
return ProcessUtils.readByte(this.handle, address);
return ProcessUtils.readByte(this.handle, address, this.bitness);
}

readShort(address: number): number {
return ProcessUtils.readShort(this.handle, address);
return ProcessUtils.readShort(this.handle, address, this.bitness);
}

readInt(address: number): number {
return ProcessUtils.readInt(this.handle, address);
return ProcessUtils.readInt(this.handle, address, this.bitness);
}

readUInt(address: number): number {
return ProcessUtils.readUInt(this.handle, address);
return ProcessUtils.readUInt(this.handle, address, this.bitness);
}

readPointer(address: number): number {
return this.readIntPtr(this.readIntPtr(address));
}

readLong(address: number): number {
return ProcessUtils.readLong(this.handle, address);
return ProcessUtils.readLong(this.handle, address, this.bitness);
}

readFloat(address: number): number {
return ProcessUtils.readFloat(this.handle, address);
return ProcessUtils.readFloat(this.handle, address, this.bitness);
}

readDouble(address: number): number {
return ProcessUtils.readDouble(this.handle, address);
return ProcessUtils.readDouble(this.handle, address, this.bitness);
}

readSharpString(address: number): string {
Expand Down

0 comments on commit 90881ef

Please sign in to comment.