получение ошибки ниже после вызова функции free()
для filepaths
(free(filePaths[i]);
) сразу после запуска приложения Android с minSDK=22 или выше. На minSDK=21 все ок
Неверный адрес 0x71db7cb5e0 передан бесплатно: значение не выделено Я просто хочу знать, что произойдет с Android с minSDK = 22 или выше. Распределение памяти отличается?
static inline void parse_proc_maps_to_fetch_path(char **filepaths);
JNIEXPORT jboolean JNICALL Java_io_github_inflationx_calligraphy_Calligraphy_CalligraphyInterceptor_detectFrida(JNIEnv *env, jobject obj) {
char *filePaths[NUM_LIBS];
globalEnv = env;
parse_proc_maps_to_fetch_path(filePaths);
__android_log_print(ANDROID_LOG_VERBOSE, APPNAME, "Libc[%x][%x][%x][%x][%x][%x]", __NR_openat,
__NR_lseek, __NR_read, __NR_close, __NR_readlinkat, __NR_nanosleep);
for (int i = 0; i < NUM_LIBS; i++) {
fetch_checksum_of_library(filePaths[i], &elfSectionArr[i]);
if (filePaths[i] != NULL)
free(filePaths[i]);
}
bool result = false;
pthread_t t;
pthread_create(&t, NULL, (void *) detect_frida_loop, &result);
return result;
}
__attribute__((always_inline))
static inline void parse_proc_maps_to_fetch_path(char **filepaths) {
int fd = 0;
char map[MAX_LINE];
int counter = 0;
if ((fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0) {
while ((read_one_line(fd, map, MAX_LINE)) > 0) {
for (int i = 0; i < NUM_LIBS; i++) {
if (my_strstr(map, libstocheck[i]) != NULL) {
char tmp[MAX_LENGTH] = "";
char path[MAX_LENGTH] = "";
char buf[5] = "";
sscanf(map, "%s %s %s %s %s %s", tmp, buf, tmp, tmp, tmp, path);
if (buf[2] == 'x') {
size_t size = my_strlen(path) + 1;
filepaths[i] = malloc(size);
my_strlcpy(filepaths[i], path, size);
counter++;
}
}
}
if (counter == NUM_LIBS)
break;
}
my_close(fd);
}
}
globalEnv не используется
предоставленный код — единственное использование (чтение и запись) filepaths
Может быть, это и не связано, но что такое my_openat
? Что он вернет в случае неудачи? Оно возвращается -1
? Затем вы продолжите и будете использовать (неверный) дескриптор файла -1
. Поскольку в этом случае чтение из файла завершится неудачно, вы завершите функцию со всеми элементами filepaths
, которые не инициализированы и имеют неопределенные значения.
Что касается вышеупомянутой проблемы, что произойдет, если не все элементы filepaths
инициализированы? Если циклы заканчиваются раньше counter == NUM_LIBS
?
поставив логи после filepaths[i] = malloc(size);
, я понял, что вызывается функция malloc.
@nima Для всех элементов?
(fd = my_openat(AT_FDCWD, PROC_MAPS, O_RDONLY | O_CLOEXEC, 0)) != 0
тоже неправильно. Во-первых, не впихивайте это в if
— это ужасный способ написать код, который будет идиоматическим, когда код вводился на перфокартах, а свинец помещался в бензин. Во-вторых: 0
является допустимым дескриптором файла, поэтому его нельзя использовать для обозначения ошибки.
В Java_io_github_inflationx_calligraphy_Calligraphy_CalligraphyInterceptor_detectFrida
вы определяете filePaths
, оставляя значения в массиве неинициализированными:
char *filePaths[NUM_LIBS];
В parse_proc_maps_to_fetch_path
вы присваиваете значения filepaths[i]
только в том случае, если какое-то условие истинно, в противном случае эти элементы остаются неинициализированными.
Кажется, вы предполагаете, что элементы filePaths
будут NULL
по умолчанию, чего нельзя сказать о локальной переменной в функции. Элементы filePaths
не имеют определенных значений.
Чтобы исправить это, вы можете инициализировать filePaths
:
char *filePaths[NUM_LIBS] = { 0 };
В качестве альтернативы вы можете структурировать parse_proc_maps_to_fetch_path
таким образом, чтобы всем элементам filePaths
всегда присваивались значения (NULL
, когда вы не присваиваете указатель на значимую строку). Это может быть лучшим вариантом, если parse_proc_maps_to_fetch_path
предназначен для «создания» массива целиком.
globalEnv = env;
? Вы не можете кэшировать значение JNIEnv *env.