C函数
TODO:
整理下面多个帖子的内容
open系列
open
TODO:
- 【基本解决】iOS反越狱检测之打开文件:open
- 【已解决】iOS反越狱检测:tweak插件中hook绕过open函数
/*==============================================================================
Hook: open()
==============================================================================*/
/*
TODO: maybe need support more version:
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
int openat2(int dirfd, const char *pathname, const struct open_how *how, size_t size);
refer:
https://man7.org/linux/man-pages/man2/open.2.html
*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/open.2.html
// normally max number of open parameter is 1
int MaxSupportArgNum_open = 2;
int open(const char *path, int oflag, ...);
%hookf(int, open, const char *path, int oflag, ...){
iosLogDebug("path=%{public}s, oflag=%d", path, oflag);
bool isJbPath = false;
if(cfgHookEnable_openFileC_open){
isJbPath = isJailbreakPath(path);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
// // for debug: for system() call, temp allow /bin/sh
// if (0 == strcmp(path, "/bin/sh")){
// os_log(OS_LOG_DEFAULT, "hook_open_system: temp allow /bin/sh");
// isJbPath = false;
// }
if (isJbPath){
iosLogInfo("path=%{public}s -> isJbPath=%{bool}d", path, isJbPath);
errno = ENOENT;
iosLogDebug("set errno=%d", errno);
return OPEN_FAILED;
}
}
// Setting up some variables to get all the parameters from open
mode_t curPara, paraList[MaxSupportArgNum_open];
va_list argList;
int curParaNum = 0;
va_start(argList, oflag);
// while ((curPara = (mode_t) va_arg(argList, mode_t))) {
// paraList[curParaNum] = curPara;
// curParaNum += 1;
// os_log(OS_LOG_DEFAULT, "hook_open: [%d] curPara=%d", curParaNum, curPara);
// }
// unsigned int firstArg = va_arg(argList, mode_t)
// curPara = (mode_t) va_arg(argList, mode_t);
curPara = (mode_t) va_arg(argList, unsigned int);
// maxium is only extra 1 para, so no need while
if (0 != (int)curPara) {
paraList[curParaNum] = curPara;
curParaNum += 1;
iosLogDebug("[%d] para=%d", curParaNum, curPara);
}
va_end(argList);
iosLogDebug("curParaNum=%d, argList=%{public}s", curParaNum, argList);
// return %orig;
int openRetValue = OPEN_FAILED;
if (0 == curParaNum){
openRetValue = %orig(path, oflag);
if (isJbPath) {
iosLogInfo("%spath=%{public}s, oflag=0x%x -> isJbPath=%{bool}d -> openRetValue=%d", HOOK_PREFIX(cfgHookEnable_openFileC_open), path, oflag, isJbPath, openRetValue);
}
} else if (1 == curParaNum){
mode_t mode = paraList[0];
// os_log(OS_LOG_DEFAULT, "hook_open: mode=0x%x", mode);
openRetValue = %orig(path, oflag, mode);
if (isJbPath) {
iosLogInfo("%spath=%{public}s, oflag=0x%x, mode=0x%x -> isJbPath=%{bool}d -> openRetValue=%d", HOOK_PREFIX(cfgHookEnable_openFileC_open), path, oflag, mode, isJbPath, openRetValue);
}
}
return openRetValue;
}
fopen
TODO:
【已解决】iOS反越狱检测之打开文件:hook绕过fopen
/*==============================================================================
Hook: fopen()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/fopen.3.html
FILE* fopen(const char *filename, const char *mode);
%hookf(int, fopen, const char *filename, const char *mode){
iosLogDebug("filename=%{public}s, mode=%{public}s", filename, mode);
int retValue = FOPEN_OPEN_FAILED;
bool isJbPath = false;
if(cfgHookEnable_openFileC_fopen){
isJbPath = isJailbreakPath(filename);
if (isJbPath){
retValue = FOPEN_OPEN_FAILED;
} else {
retValue = %orig;
}
} else {
retValue = %orig;
}
// for debug
if (isJbPath) {
iosLogInfo("filename=%{public}s, mode=%{public}s -> isJbPath=%s -> retValue=%d", filename, mode, boolToStr(isJbPath), retValue);
}
return retValue;
}
opendir + __opendir2
/*==============================================================================
Hook: opendir()
==============================================================================*/
// NOTES: !!! hook opendir will cause app crash.
// detail log: SubstituteLog: SubHookFunction: substitute_hook_functions returned SUBSTITUTE_ERR_FUNC_BAD_INSN_AT_START
//// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/opendir.3.html
//DIR* opendir(const char *dirname);
//
//%hookf(DIR*, opendir, const char *dirname){
// iosLogInfo("dirname=%s", dirname);
//// return %orig;
// return %orig(dirname);
//}
/*==============================================================================
Hook: __opendir2()
==============================================================================*/
// https://opensource.apple.com/source/Libc/Libc-186/gen.subproj/opendir.c.auto.html
// https://opensource.apple.com/source/Libc/Libc-320/include/dirent.h.auto.html
DIR *__opendir2(const char *name, int flags);
%hookf(DIR*, __opendir2, const char *name, int flags){
iosLogDebug("name=%{public}s, flags=0x%x", name, flags);
DIR* openedDir = OPENDIR_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC___opendir2){
isJbPath = isJailbreakPath(name);
if (isJbPath) {
openedDir = OPENDIR_FAILED;
} else {
// openedDir = %orig(name, flags);
openedDir = %orig;
}
} else {
// openedDir = %orig(name, flags);
openedDir = %orig;
}
// for debug
if (isJbPath) {
iosLogInfo("name=%{public}s, flags=0x%x -> isJbPath=%{bool}d -> openedDir=%p", name, flags, isJbPath, openedDir);
}
return openedDir;
}
access系列
TODO:
- 【未解决】iOS反越狱检测之打开文件:access系列函数
access
/*==============================================================================
Hook: access()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/access.2.html
int access(const char *path, int amode);
%hookf(int, access, const char *path, int amode){
iosLogDebug("path=%{public}s, amode=0x%x", path, amode);
int retValue = ACCESS_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC) {
isJbPath = isJailbreakPath(path);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
if (isJbPath){
iosLogDebug("isJbPath=%{bool}d, %{public}s", isJbPath, path);
errno = ENOENT;
iosLogDebug("set errno=%d", errno);
retValue = ACCESS_FAILED;
} else {
retValue = %orig;
}
} else {
retValue = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("path=%{public}s, amode=0x%x -> isJbPath=%{bool}d, retValue=%d", path, amode, isJbPath, retValue);
}
return retValue;
}
faccessat
/*==============================================================================
Hook: faccessat()
==============================================================================*/
// https://man7.org/linux/man-pages/man2/access.2.html
// https://linux.die.net/man/2/faccessat
int faccessat(int dirfd, const char *pathname, int mode, int flags);
%hookf(int, faccessat, int dirfd, const char *pathname, int mode, int flags){
iosLogDebug("dirfd=%d, pathname=%{public}s, mode=0x%x, flags=0x%x", dirfd, pathname, mode, flags);
int retInt = ACCESS_FAILED;
bool isJbPath = false;
if(cfgHookEnable_openFileC_faccessat){
const char* absPath = NULL;
bool isAbsPath = strStartsWith(pathname, "/");
iosLogDebug("isAbsPath=%{bool}d", isAbsPath);
if (isAbsPath) {
absPath = pathname;
} else {
// is relative path
if (dirfd == AT_FDCWD){
iosLogDebug("dirfd is AT_FDCWD=%d", AT_FDCWD);
// pathname is interpreted relative to the current working directory of the calling process (like access())
// TODO: try get current working directory -> avoid caller pass the special path, finnaly is jailbreak path
// eg: current working directory is "/usr/xxx/yyy/", then pass in "../../libexec/cydia/zzz"
// finnal path is "/usr/libexec/cydia/zzz", match jailbreak path: "/usr/libexec/cydia/", is jaibreak path
// but use "../../libexec/cydia/zzz" can not check whether is jailbreak path
} else {
// get file path from dir fd
char filePath[PATH_MAX];
bool isGetPathOk = getFilePath(dirfd, filePath);
iosLogDebug("isGetPathOk=%s", boolToStr(isGetPathOk));
if (isGetPathOk) {
char* fullPath = strPathJoin(filePath, pathname)
iosLogDebug("fullPath=%{public}s", fullPath);
absPath = fullPath;
}
}
}
if (NULL != absPath){
isJbPath = isJailbreakPath(absPath);
iosLogDebug("absPath=%{public}s -> isJbPath=%{bool}d", absPath, isJbPath);
if (isJbPath) {
iosLogDebug("hook jailbreak path: %s", absPath);
retInt = ACCESS_FAILED;
} else {
retInt = %orig;
}
} else {
retInt = %orig;
}
} else {
retInt = %orig;
}
// for debug
if (isJbPath) {
iosLogInfo("%sdirfd=%d, pathname=%{public}s, mode=0x%x, flags=0x%x -> isJbPath=%{bool}d, retInt=%d",
HOOK_PREFIX(cfgHookEnable_openFileC_faccessat), dirfd, pathname, mode, flags, isJbPath, retInt);
}
return retInt;
}
realpath
/*==============================================================================
Hook: realpath()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man3/realpath.3.html
char* realpath(const char* file_name, char* resolved_name);
%hookf(char*, realpath, const char* file_name, char* resolved_name){
iosLogDebug("file_name=%{public}s, resolved_name=%p", file_name, resolved_name);
char* resolvedPath = REALPATH_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC) {
isJbPath = isJailbreakPath(file_name);
if (isJbPath) {
resolvedPath = REALPATH_FAILED;
} else {
// resolvedPath = %orig(file_name, resolved_name);
resolvedPath = %orig;
}
} else {
resolvedPath = %orig;
}
// for debug
if (isJbPath) {
iosLogInfo("file_name=%{public}s, resolved_name=%{public}s -> isJbPath=%{bool}d -> resolvedPath=%{public}s", file_name, resolved_name, isJbPath, resolvedPath);
}
return resolvedPath;
}
stat系列
TODO:
- 【已解决】iOS反越狱检测之stat:支持路径是否带斜杠结尾以及包含点和两个点
- 【已解决】iOS反越狱之stat函数测试机文件列表对于非越狱手是否正常
- 【部分解决】iOS反越狱检测的其他版本stat函数:stat64
- 【已解决】iOS反越狱检测:hook绕过stat函数的实现机制和方式
stat
/*==============================================================================
Hook: stat()
==============================================================================*/
int stat(const char *pathname, struct stat *buf);
%hookf(int, stat, const char *pathname, struct stat *buf){
int statRet = STAT_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC) {
isJbPath = isJailbreakPath(pathname);
iosLogDebug("pathname=%{public}s -> isJbPath=%s", pathname, boolToStr(isJbPath));
if (isJbPath){
statRet = STAT_FAILED;
} else {
statRet = %orig;
}
} else {
statRet = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("pathname=%{public}s -> isJbPath=%s -> statRet=%d", pathname, boolToStr(isJbPath), statRet);
}
return statRet;
}
lstat
/*==============================================================================
Hook: lstat()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/lstat.2.html
int lstat(const char* path, struct stat* buf);
%hookf(int, lstat, const char* path, struct stat* buf){
iosLogDebug("path=%{public}s, buf=%p", path, buf);
int lstatRet = STAT_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC) {
isJbPath = isJailbreakPath(path);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
if (isJbPath){
lstatRet = STAT_FAILED;
} else {
lstatRet = %orig;
}
} else {
lstatRet = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("path=%{public}s -> isJbPath=%s -> lstatRet=%d", path, boolToStr(isJbPath), lstatRet);
}
return lstatRet;
}
fstat
/*==============================================================================
Hook: fstat()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/fstat.2.html
int fstat(int fd, struct stat *buf);
%hookf(int, fstat, int fd, struct stat *buf){
iosLogDebug("fd=%d, buf=%p", fd, buf);
int retInt = STAT_FAILED;
bool isJbPath = false;
char parsedPath[PATH_MAX];
memset(parsedPath, 0, PATH_MAX);
if (cfgHookEnable_openFileC) {
// get file path from fd
bool isGetPathOk = getFilePath(fd, parsedPath);
iosLogDebug("isGetPathOk=%s, parsedPath=%s", boolToStr(isGetPathOk), parsedPath);
if (isGetPathOk) {
isJbPath = isJailbreakPath(parsedPath);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
if (isJbPath){
retInt = STAT_FAILED;
} else {
retInt = %orig;
}
} else {
// can not get path -> can not check is jailbreak or not -> not hook
retInt = %orig;
}
} else {
retInt = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("fd=%d,buf=%p -> parsedPath=%{public}s -> isJbPath=%s -> retInt=%d", fd, buf, parsedPath, boolToStr(isJbPath), retInt);
}
return retInt;
}
fstatat
/*==============================================================================
Hook: fstatat()
==============================================================================*/
// https://man7.org/linux/man-pages/man3/fstatat.3p.html
// https://linux.die.net/man/2/fstatat
//int fstatat(int dirfd, const char *pathname, struct stat *buf, int flags);
//int fstatat(int fd, const char *restrict path, struct stat *restrict buf, int flag);
int fstatat(int fd, const char* pathname, struct stat* buf, int flags);
%hookf(int, fstatat, int fd, const char* pathname, struct stat* buf, int flags){
iosLogDebug("fd=%d, pathname=%{public}s, buf=%p, flags=0x%x", fd, pathname, buf, flags);
int fstatatRet = STATFS_FAILED;
bool isJbPath = false;
if(cfgHookEnable_openFileC){
const char* absPath = NULL;
bool isAbsPath = strStartsWith(pathname, "/");
iosLogDebug("isAbsPath=%{bool}d", isAbsPath);
if (isAbsPath) {
absPath = pathname;
} else {
// is relative path
if (fd == AT_FDCWD){
iosLogDebug("fd is AT_FDCWD=%d", AT_FDCWD);
// pathname is interpreted relative to the current working directory of the calling process (like access())
// TODO: try get current working directory -> avoid caller pass the special path, finnaly is jailbreak path
// eg: current working directory is "/usr/xxx/yyy/", then pass in "../../libexec/cydia/zzz"
// finnal path is "/usr/libexec/cydia/zzz", match jailbreak path: "/usr/libexec/cydia/", is jaibreak path
// but use "../../libexec/cydia/zzz" can not check whether is jailbreak path
} else {
// get file path from dir fd
char filePath[PATH_MAX];
bool isGetPathOk = getFilePath(fd, filePath);
iosLogDebug("isGetPathOk=%s", boolToStr(isGetPathOk));
if (isGetPathOk) {
char* fullPath = strPathJoin(filePath, pathname)
iosLogDebug("fullPath=%{public}s", fullPath);
absPath = fullPath;
}
}
}
if (NULL != absPath){
isJbPath = isJailbreakPath(absPath);
iosLogDebug("absPath=%{public}s -> isJbPath=%{bool}d", absPath, isJbPath);
if (isJbPath) {
iosLogDebug("hook jailbreak path: %s", absPath);
fstatatRet = STATFS_FAILED;
} else {
fstatatRet = %orig;
}
} else {
fstatatRet = %orig;
}
} else {
fstatatRet = %orig;
}
// for debug
if (isJbPath) {
iosLogInfo("fd=%d, pathname=%{public}s, buf=%p, flags=0x%x -> isJbPath=%{bool}d -> fstatatRet=%d", fd, pathname, buf, flags, isJbPath, fstatatRet);
}
return fstatatRet;
}
statfs
/*==============================================================================
Hook: statfs()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/statfs.2.html
int statfs(const char *path, struct statfs *buf);
%hookf(int, statfs, const char *path, struct statfs *buf){
iosLogDebug("path=%{public}s, buf=%p", path, buf);
int statfsRet = STATFS_FAILED;
bool isJbPath = false;
if (cfgHookEnable_openFileC) {
isJbPath = isJailbreakPath(path);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
if (isJbPath){
statfsRet = STATFS_FAILED;
} else {
statfsRet = %orig;
}
} else {
statfsRet = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("found jailbreak path: path=%{public}s -> isJbPath=%s -> statfsRet=%d", path, boolToStr(isJbPath), statfsRet);
}
return statfsRet;
}
fstatfs
/*==============================================================================
Hook: fstatfs()
==============================================================================*/
// https://developer.apple.com/library/archive/documentation/System/Conceptual/ManPages_iPhoneOS/man2/statfs64.2.html
int fstatfs(int fd, struct statfs *buf);
%hookf(int, fstatfs, int fd, struct statfs *buf){
iosLogDebug("fd=%d, buf=%p", fd, buf);
int fstatfsRet = STATFS_FAILED;
bool isJbPath = false;
char parsedPath[PATH_MAX];
memset(parsedPath, 0, PATH_MAX);
if (cfgHookEnable_openFileC) {
// get file path from fd
bool isGetPathOk = getFilePath(fd, parsedPath);
iosLogDebug("isGetPathOk=%s, parsedPath=%s", boolToStr(isGetPathOk), parsedPath);
if (isGetPathOk) {
isJbPath = isJailbreakPath(parsedPath);
iosLogDebug("isJbPath=%{bool}d", isJbPath);
if (isJbPath){
fstatfsRet = STATFS_FAILED;
} else {
fstatfsRet = %orig;
}
} else {
// can not get path -> can not check is jailbreak or not -> not hook
fstatfsRet = %orig;
}
} else {
fstatfsRet = %orig;
}
// for debug
if(isJbPath){
iosLogInfo("fd=%d,buf=%p -> parsedPath=%{public}s -> isJbPath=%s -> fstatfsRet=%d", fd, buf, parsedPath, boolToStr(isJbPath), fstatfsRet);
}
return fstatfsRet;
}