Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

doorstop.log file #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 104 additions & 23 deletions doorstop.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ void (*r_mono_set_assemblies_path)(const char *path);

void *(*r_mono_image_open_from_data_with_name)(void *data, uint32_t data_len, int need_copy, void *status, int refonly, const char *name);

void *(*r_mono_object_to_string)(void *obj, void **exc);
char *(*r_mono_string_to_utf8)(void *s);

void doorstop_init_mono_functions(void *handle)
{
Expand All @@ -85,32 +87,63 @@ void doorstop_init_mono_functions(void *handle)
LOAD_METHOD(mono_set_assemblies_path);
LOAD_METHOD(mono_image_open_from_data_with_name);

LOAD_METHOD(mono_object_to_string);
LOAD_METHOD(mono_string_to_utf8);

#undef LOAD_METHOD
}

#define LOG(message) \
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no real idea how c works.
So if anybody knows how to create a proper log-method, I am open for suggestions.

{ \
fprintf(stdout, "[Doorstop] "); \
fprintf(stdout, message); \
\
fprintf(log_handle, "[Doorstop] "); \
fprintf(log_handle, message); \
\
fflush(log_handle); \
fflush(stdout); \
}

#define LOGF(message, ...) \
{ \
fprintf(log_handle, "[Doorstop] "); \
fprintf(log_handle, message, __VA_ARGS__); \
\
fprintf(stdout, "[Doorstop] "); \
fprintf(stdout, message, __VA_ARGS__); \
\
fflush(log_handle); \
fflush(stdout); \
}

static FILE *log_handle;

void *jit_init_hook(const char *root_domain_name, const char *runtime_version)
{
LOG("jit_init_hook invoked\n");

char *override = getenv("DOORSTOP_CORLIB_OVERRIDE_PATH");
DIR *override_dir = override ? opendir(override) : NULL;
char *assembly_dir = r_mono_assembly_getrootdir();
if (override && override_dir) {
closedir(override_dir);
printf("Got override: %s\n", override);
printf("Current root dir: %s\n", assembly_dir);
LOGF("Got override: %s\n", override);
LOGF("Current root dir: %s\n", assembly_dir);

char bcl_root_full[PATH_MAX] = "\0";
realpath(override, bcl_root_full);
printf("New root path: %s\n", bcl_root_full);
LOGF("New root path: %s\n", bcl_root_full);

char *search_path;
asprintf(&search_path, "%s:%s", bcl_root_full, assembly_dir);
printf("Search path: %s\n", search_path);
LOGF("Search path: %s\n", search_path);

r_mono_set_assemblies_path(search_path);
setenv("DOORSTOP_DLL_SEARCH_DIRS", search_path, 1);
free(search_path);
} else {
printf("No override (or failed to find), unsetting.\n");
LOG("No override (or failed to find), unsetting.\n");
unsetenv("DOORSTOP_CORLIB_OVERRIDE_PATH");
setenv("DOORSTOP_DLL_SEARCH_DIRS", assembly_dir, 1);
}
Expand All @@ -122,7 +155,7 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)

if (getenv("DOORSTOP_INITIALIZED"))
{
printf("DOORSTOP_INITIALIZED is set! Skipping!\n");
LOG("DOORSTOP_INITIALIZED is set! Skipping!\n");
return domain;
}
setenv("DOORSTOP_INITIALIZED", "TRUE", TRUE);
Expand All @@ -137,13 +170,14 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)
strcat(config_path, ".config");
char *folder_path = dirname(app_path);

printf("Setting config paths; basedir: %s; config: %s\n", folder_path, config_path);
LOGF("Setting config paths; basedir: %s; config: %s\n", folder_path, config_path);
r_mono_domain_set_config(domain, folder_path, config_path);
}

char *dll_path = getenv("DOORSTOP_INVOKE_DLL_PATH");
LOGF("DOORSTOP_INVOKE_DLL_PATH: %s\n", dll_path);

printf("Managed dir: %s\n", assembly_dir);
LOGF("Managed dir: %s\n", assembly_dir);
setenv("DOORSTOP_MANAGED_FOLDER_DIR", assembly_dir, TRUE);
free(assembly_dir);

Expand All @@ -156,18 +190,18 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)

if (assembly == NULL)
{
printf("Failed to load assembly\n");
LOGF("Failed to load assembly '%s'\n", dll_path);
return domain;
}

// Get assembly's image that contains CIL code
void *image = r_mono_assembly_get_image(assembly);

printf("Got image: %p \n", image);
LOGF("Got image: %p \n", image);

if (image == NULL)
{
printf("Failed to locate the image!\n");
LOG("Failed to locate the image!\n");
return domain;
}

Expand All @@ -181,9 +215,13 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)

if (method == NULL)
{
printf("Failed to locate any entrypoints!\n");
LOGF("Failed to locate any entrypoints in '%s'!\n", dll_path);
return domain;
}
else
{
LOGF("Found entrypoints in '%s'!\n", dll_path);
}

void *signature = r_mono_method_signature(method);

Expand All @@ -200,7 +238,34 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)
args[0] = args_array;
}

r_mono_runtime_invoke(method, NULL, args, NULL);
LOG("Invoking entrypoint\n");

void *exc;

// invoke the main method of the target assembly
r_mono_runtime_invoke(method, NULL, args, &exc);

LOG("Invoking done!\n");

if(exc)
{
// some managed exception occured in the target assembly.
// try to print the exception.
LOG("Exception thrown while invoking assembly entrypoint!\n");

void *exc_str = r_mono_object_to_string(exc, NULL);
if (exc_str)
{
char *s = r_mono_string_to_utf8(exc_str);
LOGF("Exception: %s\n", s);
}
else
{
LOG("Unable to obtain exception text");
}

exit(1);
}

if (args != NULL)
{
Expand All @@ -212,21 +277,22 @@ void *jit_init_hook(const char *root_domain_name, const char *runtime_version)
}

void *hook_mono_image_open_from_data_with_name(void *data, uint32_t data_len, int need_copy, void *status, int refonly, char *name) {
printf("Load DLL: %s\n", name);
LOGF("Load DLL: %s\n", name);

void *result = NULL;
char *override = getenv("DOORSTOP_CORLIB_OVERRIDE_PATH");
if (override) {
char override_full[PATH_MAX] = "\0";
realpath(override, override_full);

char *filename = basename(name);
printf("Base: %s\n", filename);
LOGF("Base: %s\n", filename);

char *new_path;
asprintf(&new_path, "%s/%s", override_full, filename);

if (access(new_path, F_OK) == 0) {
printf("Redirecting to %s\n", new_path);
LOGF("Redirecting to %s\n", new_path);
FILE *f = fopen(new_path, "rb");
fseek(f, 0, SEEK_END);
long size = ftell(f);
Expand All @@ -245,17 +311,21 @@ void *hook_mono_image_open_from_data_with_name(void *data, uint32_t data_len, in

static char inited = 0;
void *dlsym_hook(void *handle, const char *name) {

if (!strcmp(name, "mono_jit_init_version"))
{
if (!inited) {
LOG("intercepting mono_jit_init_version\n");
doorstop_init_mono_functions(handle);
inited = 1;
}
return (void *)jit_init_hook;
}
if (!strcmp(name, "mono_image_open_from_data_with_name")) {
if (!inited) {
else if (!strcmp(name, "mono_image_open_from_data_with_name"))
{
if (!inited)
{
LOG("intercepting mono_image_open_from_data_with_name\n");
doorstop_init_mono_functions(handle);
inited = 1;
}
Expand All @@ -279,6 +349,17 @@ __attribute__ ((constructor)) void doorstop_setup() {
return;
}

log_handle = fopen("doorstop.log", "w");

if (log_handle == NULL)
{
printf("[Doorstop] unable to create logfile\n");
}
else
{
printf("[Doorstop] creating logfile 'doorstop.log'\n");
}

plthook_t *hook;

// Some versions of Unity (especially macOS) ship with UnityPlayer shared lib
Expand All @@ -292,18 +373,18 @@ __attribute__ ((constructor)) void doorstop_setup() {
#endif

if(unity_player && plthook_open_by_handle(&hook, unity_player) == 0) {
printf("Found UnityPlayer, hooking into it instead\n");
LOG("Found UnityPlayer, hooking into it instead\n");
}
else if(plthook_open(&hook, NULL) != 0) {
printf("Failed to open current process PLT! Cannot run Doorstop! Error: %s\n", plthook_error());
LOGF("Failed to open current process PLT! Cannot run Doorstop! Error: %s\n", plthook_error());
return;
}

if(plthook_replace(hook, "dlsym", &dlsym_hook, NULL) != 0)
printf("Failed to hook dlsym, ignoring it. Error: %s\n", plthook_error());
LOGF("Failed to hook dlsym, ignoring it. Error: %s\n", plthook_error());

if(plthook_replace(hook, "fclose", &fclose_hook, NULL) != 0)
printf("Failed to hook fclose, ignoring it. Error: %s\n", plthook_error());
LOGF("Failed to hook fclose, ignoring it. Error: %s\n", plthook_error());

#if __APPLE__
/*
Expand Down