文件重定向是一个文件重定位到另外一个文件。重定向后,当一个文件的发生打开,读写这些行为,就会变成另外一个文件的打开,读写。
文件重定向多用于过风控,改机,多开等场景中。
作为实现重定向的一方,有许多实现方式,下面的例子是用frida脚本hook libc.so下的open函数,在open函数被调用的时候,根据文件名来判断是否对打开的重定向,最后将文件描述符返回。
function strcmp(str1,str2){
let ret = -1;
for(let i = 0; ;i++){
let ch1 = str1.add(i).readU8();
let ch2 = str2.add(i).readU8();
if(ch1 == 0 && ch2 == 0){
ret = 0;
break;
}
if(ch1 != ch2){
ret = -1;
break;
}
}
return ret;
}
function redirect(src,dest){
const openPtr = Module.getExportByName('libc.so', 'open');
const open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
Interceptor.replace(openPtr, new NativeCallback((pathPtr, flags) => {
const path = pathPtr.readUtf8String();
const originPath = Memory.allocUtf8String(src)
let currentPath = Memory.allocUtf8String(path)
let fd = -1
if(strcmp(currentPath,originPath) == 0){
console.warn('redirect file "' + path + '" to "' + dest + '"');
let targetPath = Memory.allocUtf8String(dest)
fd = open(targetPath, flags);
}
else{
console.log('open file "' + path + '"');
fd = open(pathPtr, flags);
}
return fd;
}, 'int', ['pointer', 'int']));
}
redirect("/proc/cpuinfo","/data/data/com.luoye.fileredirectdetect/cpuinfo")
经过hook之后,当app打开/proc/cpuinfo,文件路径就被重定向到了自定义的文件路径。open函数返回的是新的文件的文件描述符。
既然hook之后返回的是新的文件的文件描述符,那么,对抗方就可以打开需要检测的文件,然后调用readlink函数反推文件路径,如果readlink返回的文件路径和打开的文件不一致,那么说明打开的文件被重定位到其他文件去了。
/**
* 检查文件是否被重定位
* @src_path 要检查的文件
* @new_path 被重定位到的路径
* @return 0 没有重定位;1 被重定位
*/
int checkFileRedirect(const char *src_path,char *new_path,size_t max_len) {
int src_fd = open(src_path,O_RDONLY);
if(src_fd < 0){
return 0;
}
int ret = 0;
char link_path[128] = {0};
snprintf(link_path, sizeof(link_path), "/proc/%d/fd/%d", getpid(), src_fd);
char fd_path[256] = {0};
int link = readlink(link_path, fd_path, sizeof(fd_path));
if(link < 0){
return 0;
}
size_t len = strnlen(fd_path,256);
if(len && strncmp(fd_path,src_path,256) != 0) {
strncpy(new_path, fd_path,max_len);
ret = 1;
}
if(src_fd > 0) {
close(src_fd);
}
return ret;
}
下图是在多开软件中检测到的路径重定向结果:
当然这只是提供的一个思路,文件重定位可以有其他实现,对抗也可以有其他实现,想要做得更好,需要更多的想象力。