void dot_so_finder(char *filename) { int file_fd; char *file_map; char *ptr; char *prev; off_t size; struct stat file_stat; file_fd = open(filename, O_RDONLY); fstat(file_fd, &file_stat); file_map = mmap(0, file_stat.st_size, PROT_READ, MAP_PRIVATE, file_fd, 0); ptr = file_map; prev = ptr; size = file_stat.st_size; while ((ptr = memmem(ptr, size, lib_ending, strlen(lib_ending))) != NULL) { if (ptr >= file_map + file_stat.st_size) break; if (char_is_valid(ptr - 1)) get_full_lib_name(ptr); size -= ptr - prev; prev = ptr; ptr++; /* Advance pointer one character to ensure we don't keep looping over the same ".so" instance over and over again */ } munmap(file_map, file_stat.st_size); close(file_fd); }
int charset_is_valid(char *s) { for (; s && *s && char_is_valid(*s); s++); return !s || !*s; }
void get_full_lib_name(char *found_lib) { char *ptr, *peek; char full_name[256] = {0}; long len; int num_chars; int i; ptr = found_lib; peek = ptr - 1; /* if there's a false-positive in finding matching ".so", but it isn't ever referencing * a library, it's probably just instructions that slipped through the cracks. In this case * we will rewind the pointer that's searching for "lib" or "egl" MAX_LIB_NAME (default 50) * times, in which we will bail out citing that it was probably a false-positive */ for (num_chars = 0; num_chars <= MAX_LIB_NAME; num_chars++) { if (!strncmp(ptr, egl_beginning, strlen(egl_beginning)) || !strncmp(ptr, lib_beginning, strlen(lib_beginning))) { peek = ptr - 1; /* the peek below would fall victim to a file which is looking directly for * "/system/lib/lib_whatever.so", because it would now point to lib/lib_whatever.so * which is not what what we want, so take the first pick if the peek character is '/' */ if (*peek == '/') { for (i = 0; blob_directories[i]; i++) { if (!strncmp(peek, blob_directories[i], strlen(blob_directories[i]))) { peek += strlen(blob_directories[i]); ptr = peek; break; } } break; } /* some libraries are called "libmmcamera_wavelet_lib.so", in which the pointer will * rewind to the first "lib" and then will pass it over to the check_emulator_for_lib * method, which will in turn bark about a missing "lib.so", so we will rewind the pointer * some extra times until it encounters an invalid character using the char_is_valid * function and if it ends up finding another instance of "lib", picks that *that* one, not * the original one, so we will get the entire library name of "libmmcamera_wavelet_lib.so" * and not just "lib.so" which would have been chosen if not for the peek. */ while (char_is_valid(peek) && *peek--) { if (!strncmp(peek, lib_beginning, strlen(lib_beginning))) { #ifdef DEBUG printf("Possible lib_lib.so! %s\n", peek); #endif ptr = peek; } } break; } if (num_chars == MAX_LIB_NAME) { #ifdef DEBUG printf("Character limit exceeded! Full string was:\n"); for (num_chars = 0; num_chars < MAX_LIB_NAME + strlen(lib_beginning); num_chars++) { printf("%c", *ptr); ptr++; } printf("\n"); #endif return; } ptr--; peek--; } len = (long)(found_lib + strlen(lib_beginning)) - (long)ptr; strncpy(full_name, ptr, len); check_emulator_for_lib(full_name); }