-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathlibhookexecv.c
66 lines (51 loc) · 1.58 KB
/
libhookexecv.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include <stdlib.h>
/* Author: https://github.com/Hackerl/
* https://github.com/Hackerl/Wine_Appimage/issues/11#issuecomment-447834456
* sudo apt-get -y install gcc-multilib
* gcc -shared -fPIC -ldl libhookexecv.c -o libhookexecv.so
* for i386: gcc -shared -fPIC -m32 -ldl libhookexecv.c -o libhookexecv.so
*
* hook wine execv syscall. use special ld.so
* */
typedef int(*EXECV)(const char*, char**);
static inline int strendswith( const char* str, const char* end )
{
size_t len = strlen( str );
size_t tail = strlen( end );
return len >= tail && !strcmp( str + len - tail, end );
}
int execv(char *path, char ** argv)
{
static void *handle = NULL;
static EXECV old_execv = NULL;
char **last_arg = argv;
if( !handle )
{
handle = dlopen("libc.so.6", RTLD_LAZY);
old_execv = (EXECV)dlsym(handle, "execv");
}
char * wineloader = getenv("WINELDLIBRARY");
if (wineloader == NULL)
{
return old_execv(path, argv);
}
while (*last_arg) last_arg++;
char ** new_argv = (char **) malloc( (last_arg - argv + 2) * sizeof(*argv) );
memcpy( new_argv + 1, argv, (last_arg - argv + 1) * sizeof(*argv) );
char * pathname = NULL;
char hookpath[256];
memset(hookpath, 0, 256);
if (strendswith(path, "wine-preloader"))
{
strcat(hookpath, path);
strcat(hookpath, "_hook");
wineloader = hookpath;
}
new_argv[0] = wineloader;
int res = old_execv(wineloader, new_argv);
free( new_argv );
return res;
}