[Unix] Centos 7, can't see process in process list.
Compiled ReClass.NET for unix and tried to open an x86 process with the x86 binary, but it does not show in the list, both processes run as root.. As a safe measure I ran the x64 binary as well and same result. I can see the process in Cheat Engine, but not this. Any ideas ?
Do you see an other process? Only that one is missing?
Sorry for the lack of info. I can see the rest of the processes, I have a few game server files started with systemd that aren't discovered by ReClass.NET.
Here's an example
https://i.imgur.com/dom5i10.png
Here's it viewable from CE.
https://i.imgur.com/VutjuGc.png
Processes are 32 bit, as you can see I am running the x86 bin for ReClass.NET, maybe the issue is with the process being started by systemd ?
ReClass does the following on Unix to detect processes:
- Iterate all directories in
/proc - Resolve the symlink
/proc/<pid>/exeto get the path to the application - Read
/proc/<pid>/auxvto get the platform
If 2 or 3 fail the process is skipped. Could you tests these steps manually with the user running ReClass.NET?
2 would be readlink /proc/<pid>/exe and 3 cat /proc/<pid>/auxv
Here it is:
➜ /proc readlink /proc/4536/exe
/usr/bin/WorldSvr
➜ /proc cat /proc/4536/auxv
4s�!0s����d4� @s� 0
Kܻ����[ܻ�#
Could you compile and test this so we see which one fails:
#include <iostream>
#include <fstream>
#include <filesystem>
namespace fs = std::filesystem;
bool is_number(const std::string& s)
{
auto it = s.begin();
for (; it != s.end() && std::isdigit(*it); ++it);
return !s.empty() && it == s.end();
}
enum class Platform
{
Unknown,
X86,
X64
};
Platform GetProcessPlatform(const std::string& auxvPath)
{
auto platform = Platform::Unknown;
std::ifstream file(auxvPath);
if (file)
{
char buffer[16];
while (true)
{
file.read(buffer, 16);
if (!file)
{
return Platform::X64;
}
if (buffer[4] != 0 || buffer[5] != 0 || buffer[6] != 0 || buffer[7] != 0)
{
return Platform::X86;
}
}
}
return platform;
}
int main(int argc, char *argv[])
{
fs::path procPath("/proc");
std::cout << "Root: " << procPath << "\n";
if (fs::is_directory(procPath))
{
for (auto& d : fs::directory_iterator(procPath))
{
std::cout << "\n";
if (fs::is_directory(d))
{
std::cout << "Directory: " << d << "\n";
auto processPath = d.path();
auto name = processPath.filename().string();
std::cout << "Name: " << name << "\n";
if (is_number(name))
{
auto exeSymLink = processPath / "exe";
if (fs::is_symlink(fs::symlink_status(exeSymLink)))
{
std::error_code ec;
auto linkPath = read_symlink(exeSymLink, ec).string();
if (!ec)
{
std::cout << "Proc Path: " << linkPath << "\n";
auto auxvPath = processPath / "auxv";
auto platform = GetProcessPlatform(auxvPath.string());
std::cout << "Platform: " << (int)platform << "\n";
}
else
{
std::cout << "Error: read_symlink failed\n";
}
}
else
{
std::cout << "Error: is_symlink failed\n";
}
}
else
{
std::cout << "Error: Is not a number\n";
}
}
else
{
std::cout << "Not a directory: " << d << "\n";
}
}
}
else
{
std::cout << "Error: is_directory\n";
}
return 0;
}
Compile it with g++ -std=c++17 -o proc proc.cpp
Output for WorldSvr from the compiled proc
Directory: "/proc/4536"
Name: 4536
Proc Path: /usr/bin/WorldSvr
Platform: 1
Could you please change the code and test again (I hope is it fails now):
#include <unistd.h>
fs::path my_read_symlink(const fs::path& p, std::error_code& ec)
{
fs::path symlink_path;
std::string temp(64, '\0');
for (;; temp.resize(temp.size() * 2))
{
ssize_t result;
if ((result = ::readlink(p.c_str(), /*temp.data()*/ &temp[0], temp.size())) == -1)
{
ec.assign(errno, std::system_category());
break;
}
else
{
if (result != static_cast<ssize_t>(temp.size()))
{
symlink_path = fs::path(std::string(temp.begin(), temp.begin() + result));
ec.clear();
break;
}
}
}
return symlink_path;
}
...
//auto linkPath = fs::read_symlink(exeSymLink, ec).string();
auto linkPath = my_read_symlink(exeSymLink, ec).string();
...
Still same output with updated code
Directory: "/proc/4536"
Name: 4536
Proc Path: /usr/bin/WorldSvr
Platform: 1
Maybe it's not the native code... Could you recompile ReClass.NET with this change:
diff --git a/ReClass.NET/Program.cs b/ReClass.NET/Program.cs
index f28cb0bd..1a1d16ca 100644
--- a/ReClass.NET/Program.cs
+++ b/ReClass.NET/Program.cs
@@ -82,6 +82,11 @@ namespace ReClassNET
{
RemoteProcess = new RemoteProcess(coreFunctions);
+ foreach (var p in Program.CoreFunctions.EnumerateProcesses())
+ {
+ Program.Logger.Log(LogLevel.Error, $"{p.Id} {p.Name} {p.Path}");
+ }
+
MainForm = new MainForm();
Application.Run(MainForm);
That will log all available processes. Is WorldSvr logged?
Recompiled and ran, but I don't see any logs in stdout, I'm starting the program with mono ReClass.NET.exe, are the logs somewhere else ?
Edit: I'm gonna install the vscode extension for mono debugging and try to debug it, will get back to you.
Just saw the diagnostic window, lol. No WorldSvr logged there.
That's strange... EnumerateProcesses calls the native code and from the other tests that works.
Next try: Use this code with the NativeCore.so from ReClass.NET.
#include <iostream>
#include <locale>
#include <codecvt>
#include <string>
#include <dlfcn.h>
#pragma pack(push, 1)
struct EnumerateProcessData
{
size_t Id;
char16_t Name[260];
char16_t Path[260];
};
#pragma pack(pop)
typedef void(EnumerateProcessCallback)(EnumerateProcessData* data);
int main(int argc, char *argv[])
{
auto handle = dlopen("./NativeCore.so", 2);
auto fn = (void(*)(EnumerateProcessCallback callbackProcess))dlsym(handle, "EnumerateProcesses");
fn([](EnumerateProcessData* data) {
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> codecvt;
std::cout << "Id: " << data->Id << " Name: " << codecvt.to_bytes(data->Name) << " Path: " << codecvt.to_bytes(data->Path) << "\n";
});
dlclose(handle);
return 0;
}
Compiled and ran, WorldSvr proc is missing from the output
I found the issue.
https://i.imgur.com/6056kmI.png
The platform check that happens in NativeCore.so will always fail to show x86 I think ? Recompiled without it and I can see the process.
Does CFLAGS = -Wall -fPIC -DRECLASSNET64=1 set to always 1 in Makefile result in RECLASSNET64 always being true ? I don't have that much exp with cflags..
You are right. The makefile only uses the x64 mode. I will add a platform switch tomorrow. Thank you for finding the error 👍
Thanks for taking the time to help me through it :D
Did you ever push an update for this @KN4CK3R? I'm having this issue now where I can only interact with x64 processes in linux, regardless of which reclass binary i run
No, sorry. I will have a look at the Makefile ... tomorrow 🥲
Added the updated Makefile in 2e48bce. Could you test it? Should build binaries for x86 and x64 now.
Added the updated
Makefilein 2e48bce. Could you test it? Should build binaries for x86 and x64 now.
@KN4CK3R Sorry for the slow reply. Something seems to be wrong with the x86 NativeCore.so
~/Documents/GitHub/ReClass.NET$ mono ./build/Debug/x86/ReClass.NET.exe
Gtk-Message: 13:39:02.489: Failed to load module "canberra-gtk-module"
Unhandled Exception:
System.IO.FileNotFoundException: Failed to load native core functions! Couldnt find at location /home/user/Documents/GitHub/ReClass.NET/build/Debug/x86/NativeCore.so
at ReClassNET.Core.InternalCoreFunctions.Create () [0x0003e] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
at ReClassNET.Core.CoreFunctionsManager..ctor () [0x00013] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
at ReClassNET.Program.Main (System.String[] args) [0x000f0] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.IO.FileNotFoundException: Failed to load native core functions! Couldnt find at location /home/user/Documents/GitHub/ReClass.NET/build/Debug/x86/NativeCore.so
at ReClassNET.Core.InternalCoreFunctions.Create () [0x0003e] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
at ReClassNET.Core.CoreFunctionsManager..ctor () [0x00013] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
at ReClassNET.Program.Main (System.String[] args) [0x000f0] in <2ce2f9ecdfc847ab95f5f713d10f4155>:0
The file is there and if I replace it with the x64 NativeCore.so it runs but obviously only shows x64 processes