Skip to content

Commit 67d7efa

Browse files
committed
improve: SoList hiding when not dlclosed
This commit improves the hiding of a module from SoList-based detections when it does not opt to be "dlclose"d by ReZygisk. In some scenarios, the debug map would still be abnormal despite being removed manually, so, to avoid that, we call the full "soinfo_unload". However, this would call the deconstructors of the Zygisk module, causing issues in execution due to access to unitialized variables, hence we need to trick the linker into thinking it does not have deconstructors by setting the deconstructor array size to 0, and the deconstructor function to "NULL".
1 parent 046a659 commit 67d7efa

1 file changed

Lines changed: 66 additions & 55 deletions

File tree

loader/src/injector/solist.c

Lines changed: 66 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@
2020
size_t solist_realpath_offset = 0x174;
2121
#endif
2222

23+
size_t solist_fini_array_size_offset = 0x0;
24+
size_t solist_fini_offset = 0x0;
25+
2326
static const char *(*get_realpath_sym)(SoInfo *) = NULL;
24-
static void (*soinfo_free)(SoInfo *) = NULL;
27+
static void (*soinfo_unload)(SoInfo *) = NULL;
2528
static SoInfo *(*find_containing_library)(const void *p) = NULL;
2629
struct link_map *r_debug_tail = NULL;
2730

@@ -60,6 +63,8 @@ static SoInfo *somain = NULL;
6063
static size_t *g_module_load_counter = NULL;
6164
static size_t *g_module_unload_counter = NULL;
6265

66+
static struct link_map *find_link_map(SoInfo *si);
67+
6368
static bool solist_init() {
6469
#ifdef __LP64__
6570
ElfImg *linker = ElfImg_create("/system/bin/linker64", NULL);
@@ -102,37 +107,25 @@ static bool solist_init() {
102107
if (get_realpath_sym == NULL) {
103108
LOGE("Failed to find get_realpath __dl__ZNK6soinfo12get_realpathEv");
104109

105-
ElfImg_destroy(linker);
106-
107-
somain = NULL;
108-
109-
return false;
110+
goto solist_init_error;
110111
}
111112

112113
LOGD("%p is get_realpath", (void *)get_realpath_sym);
113114

114-
soinfo_free = (void (*)(SoInfo *))getSymbAddressByPrefix(linker, "__dl__ZL11soinfo_freeP6soinfo");
115-
if (soinfo_free == NULL) {
116-
LOGE("Failed to find soinfo_free __dl__ZL11soinfo_freeP6soinfo*");
117-
118-
ElfImg_destroy(linker);
119-
120-
somain = NULL;
115+
soinfo_unload = (void (*)(SoInfo *))getSymbAddressByPrefix(linker, "__dl__ZL13soinfo_unloadP6soinfo");
116+
if (soinfo_unload == NULL) {
117+
LOGE("Failed to find soinfo_unload __dl__ZL13soinfo_unloadP6soinfo*");
121118

122-
return false;
119+
goto solist_init_error;
123120
}
124121

125-
LOGD("%p is soinfo_free", (void *)soinfo_free);
122+
LOGD("%p is soinfo_unload", (void *)soinfo_unload);
126123

127124
find_containing_library = (SoInfo *(*)(const void *))getSymbAddress(linker, "__dl__Z23find_containing_libraryPKv");
128125
if (find_containing_library == NULL) {
129126
LOGE("Failed to find find_containing_library __dl__Z23find_containing_libraryPKv");
130127

131-
ElfImg_destroy(linker);
132-
133-
somain = NULL;
134-
135-
return false;
128+
goto solist_init_error;
136129
}
137130

138131
LOGD("%p is find_containing_library", (void *)find_containing_library);
@@ -141,54 +134,74 @@ static bool solist_init() {
141134
if (r_debug_tail == NULL) {
142135
LOGE("Failed to find r_debug_tail __dl__ZL10r_debug_tail");
143136

144-
ElfImg_destroy(linker);
137+
goto solist_init_error;
138+
}
145139

146-
somain = NULL;
140+
SoInfo *solinker = (SoInfo *)getSymbValueByPrefix(linker, "__dl__ZL8solinker");
141+
if (solinker == NULL) {
142+
LOGE("Failed to find solinker __dl__ZL8solinker");
147143

148-
return false;
144+
goto solist_init_error;
145+
}
146+
147+
LOGD("%p is solinker", (void *)solinker);
148+
149+
struct link_map *solinker_map = find_link_map(solinker);
150+
if (solinker_map == NULL) {
151+
LOGE("Failed to find link_map for solinker");
152+
153+
goto solist_init_error;
149154
}
150155

156+
LOGD("%p is solinker_map", (void *)solinker_map);
157+
151158
g_module_load_counter = (size_t *)getSymbAddress(linker, "__dl__ZL21g_module_load_counter");
152159
if (g_module_load_counter != NULL) LOGD("found symbol g_module_load_counter");
153160

154161
g_module_unload_counter = (size_t *)getSymbAddress(linker, "__dl__ZL23g_module_unload_counter");
155162
if (g_module_unload_counter != NULL) LOGD("found symbol g_module_unload_counter");
156163

164+
ElfImg_destroy(linker);
165+
157166
for (size_t i = 0; i < 1024 / sizeof(void *); i++) {
158167
size_t possible_size_of_somain = *(size_t *)((uintptr_t)somain + i * sizeof(void *));
159168

160-
if (possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100) {
169+
if (solist_size_offset == 0 && possible_size_of_somain < 0x100000 && possible_size_of_somain > 0x100) {
161170
solist_size_offset = i * sizeof(void *);
162171

163172
LOGD("solist_size_offset is %zu * %zu = %p", i, sizeof(void *), (void *)solist_size_offset);
173+
}
174+
175+
struct link_map *possible_link_map_head = (struct link_map *)((uintptr_t)solinker + i * sizeof(void *));
176+
if (possible_link_map_head->l_name == solinker_map->l_name) {
177+
178+
#ifdef __arm__
179+
/* INFO: For arm32, ARM_exidx and ARM_exidx_count is defined between them. */
180+
solist_fini_array_size_offset = (i - 6) * sizeof(void *);
181+
solist_fini_offset = (i - 5) * sizeof(void *);
182+
183+
LOGD("solist_fini_array_size_offset is %zu * %zu = %p", (i - 6), sizeof(void *), (void *)solist_fini_array_size_offset);
184+
LOGD("solist_fini_offset is %zu * %zu = %p", (i - 4), sizeof(void *), (void *)solist_fini_offset);
185+
#else
186+
solist_fini_array_size_offset = (i - 4) * sizeof(void *);
187+
solist_fini_offset = (i - 2) * sizeof(void *);
188+
189+
LOGD("solist_fini_array_size_offset is %zu * %zu = %p", (i - 4), sizeof(void *), (void *)solist_fini_array_size_offset);
190+
LOGD("solist_fini_offset is %zu * %zu = %p", (i - 2), sizeof(void *), (void *)solist_fini_offset);
191+
#endif
164192

165193
break;
166194
}
167195
}
168196

169-
ElfImg_destroy(linker);
170-
171197
return true;
172-
}
173198

174-
/* INFO: This is an AOSP function to remove a link map from
175-
the link map list.
176-
177-
SOURCES:
178-
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker_gdb_support.cpp#63
179-
*/
180-
static void remove_link_map_from_debug_map(struct link_map *map) {
181-
if (r_debug_tail == map) {
182-
r_debug_tail = map->l_prev;
183-
}
199+
solist_init_error:
200+
ElfImg_destroy(linker);
184201

185-
if (map->l_prev) {
186-
map->l_prev->l_next = map->l_next;
187-
}
202+
somain = NULL;
188203

189-
if (map->l_next) {
190-
map->l_next->l_prev = map->l_prev;
191-
}
204+
return false;
192205
}
193206

194207
static struct link_map *find_link_map(SoInfo *si) {
@@ -209,13 +222,13 @@ static struct link_map *find_link_map(SoInfo *si) {
209222
SOURCES:
210223
- https://android.googlesource.com/platform/bionic/+/refs/heads/android15-release/linker/linker.cpp#283
211224
*/
212-
if (map->l_name && (uintptr_t)map->l_name == (uintptr_t)path) {
225+
if ((uintptr_t)map->l_name == (uintptr_t)path) {
213226
LOGD("Found link_map for %s: %p", path, (void *)map);
214227

215228
return map;
216229
}
217230

218-
map = map->l_next;
231+
map = map->l_prev;
219232
}
220233

221234
LOGE("Failed to find link_map for %s", path);
@@ -275,19 +288,17 @@ bool solist_drop_so_path(void *lib_memory, bool unload) {
275288
We cannot use the notify_gdb_of_unload function as it is static, and not available
276289
in all linker binaries.
277290
*/
278-
struct link_map *map = find_link_map(found);
279-
if (!map) {
280-
LOGE("Failed to find link map for %s", path);
291+
/* INFO: unregister_soinfo_tls cannot be used since module might use JNI which may
292+
require TLS, so we cannot remove it. */
293+
size_t tmp_fini_array_size = *(size_t *)((uintptr_t)found + solist_fini_array_size_offset);
294+
void **tmp_fini_array = *(void ***)((uintptr_t)found + solist_fini_offset);
281295

282-
pdg_protect();
296+
LOGD("Bypassing call to %zu destructors and deconstructor %p", tmp_fini_array_size, tmp_fini_array);
283297

284-
return false;
285-
}
298+
*(size_t *)((uintptr_t)found + solist_fini_array_size_offset) = 0;
299+
*(void ***)((uintptr_t)found + solist_fini_offset) = NULL;
286300

287-
remove_link_map_from_debug_map(map);
288-
/* INFO: unregister_soinfo_tls cannot be used since module might use JNI which may
289-
require TLS, so we cannot remove it. */
290-
soinfo_free(found);
301+
soinfo_unload(found);
291302

292303
pdg_protect();
293304
}

0 commit comments

Comments
 (0)