-
Notifications
You must be signed in to change notification settings - Fork 1
/
overwrite-dl.c
140 lines (115 loc) · 3.44 KB
/
overwrite-dl.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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <dlfcn.h>
typedef struct dl_handle {
void *handle;
char filename[256];
int ref_count;
} dl_handle;
typedef struct dl_handle_ll {
struct dl_handle *value;
struct dl_handle_ll *next;
} dl_handle_ll;
struct dl_handle_ll *dl_handle_head = NULL;
static void * (*real_dlsym)(void *, const char *)=NULL;
static void * (*real_dlopen)(const char *filename, int flags)=NULL;
static int (*real_dlclose)(void *handle)=NULL;
extern void *_dl_sym(void *, const char *, void *);
extern void *dlsym(void *handle, const char *name)
{
FILE *fp;
struct dl_handle_ll *curr = dl_handle_head;
pid_t cur_pid = getpid();
char *filename, *to_put;
if (real_dlsym == NULL)
real_dlsym=_dl_sym(RTLD_NEXT, "dlsym", dlsym);
if (!strcmp(name,"dlsym"))
return (void*)dlsym;
if (handle == RTLD_NEXT || handle == RTLD_DEFAULT)
return real_dlsym(handle,name);
size_t needed = snprintf(NULL, 0, "/tmp/dll_sym_%u", cur_pid); // get length of resulting string to malloc
filename = malloc(needed);
sprintf(filename, "/tmp/dll_sym_%u", cur_pid);
while (curr != NULL)
{
// check if handle is present in lookup linked list
if (curr->value->handle == handle)
{
needed = snprintf(NULL, 0, "%s,%s\n", curr->value->filename, name);
to_put = malloc(needed);
sprintf(to_put, "%s,%s\n", curr->value->filename, name);
fp = fopen(filename, "a");
if (fp == NULL) {
perror("fopen()");
return 0;
}
fputs(to_put, fp);
fclose(fp);
free(to_put);
break;
}
curr = curr->next;
}
free(filename);
return real_dlsym(handle, name);
}
extern void *dlopen(const char *filename, int flags)
{
void *handle;
struct dl_handle_ll *temp, *curr = dl_handle_head;
struct dl_handle *entry;
if (real_dlopen == NULL)
real_dlopen = dlsym(RTLD_NEXT, "dlopen");
handle = real_dlopen(filename, flags);
if (handle == NULL)
return 0;
while (curr != NULL)
{
if (strncmp(curr->value->filename, filename, (uint)255))
{
curr->value->ref_count++;
return handle;
}
}
entry = malloc(sizeof(struct dl_handle));
strncpy(entry->filename, filename, 255);
entry->handle = handle;
entry->ref_count = 1;
temp = malloc(sizeof(struct dl_handle_ll));
temp->value = entry;
temp->next = dl_handle_head;
dl_handle_head = temp;
return handle;
}
extern int dlclose(void *handle)
{
struct dl_handle_ll *prev = NULL, *curr = dl_handle_head;
if (real_dlclose == NULL)
real_dlclose = dlsym(RTLD_NEXT, "dlclose");
while (curr != NULL)
{
if (curr->value->handle == handle)
{
if (--(curr->value->ref_count) == 0)
{
// free from table
if (prev == NULL) //edge case
{
dl_handle_head = curr->next;
free(curr->value);
free(curr);
} else {
prev->next = curr->next;
free(curr->value);
free(curr);
}
}
break;
}
}
return real_dlclose(handle);
}