看雪安全论坛

 

 

 

 


返回   看雪安全论坛 > 移动平台 > 『Android 安全』
  登陆   注册  

发表新主题 回复
优秀帖  
主题工具 显示模式
本站声明:看雪论坛文章版权属于作者,受法律保护。没有作者书面许可不得转载。若作者同意转载,必须以超链接形式标明文章原始出处和作者信息及本声明!
ThomasKing
级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时

ThomasKing 的头像

普通会员
普通会员

资 料:
注册日期: Apr 2014
帖子: 196 ThomasKing 品行端正
精华: 7
现金: 228 Kx
致谢数: 4
获感谢文章数:19
获会员感谢数:282
1 旧 2015-04-16 20:25:29 默认 【原创】基于HOOK的Anti-debug调用点trace和Anti-anti
ThomasKing 当前离线

标 题: 【原创】基于HOOK的Anti-debug调用点trace和Anti-anti
作 者: ThomasKing
时 间: 2015-04-16,20:25:29
链 接: http://bbs.pediy.com/showthread.php?t=199671

发一个之前写的辅助调试SO的小东西,限于水平难免会有错误之处,请各位大大批评斧正,小弟感激不尽。

同时,也欢迎各位大大讨论下反调试的技术和Anti方法,让也小弟学学
-------------------------------------------------------------------------------
基于HOOK的Anti-debug调用点trace和Anti-anti
一、  概述
相信动态调试过SO的坛友对Anti并不陌生,比如读取/proc/self/status,/proc/self/task/xxx/status、stat文件查看状态TracePid和PPid,读取wchan查看进程等待,添加notify,模拟器检测等等。经过各种掉坑之后,虽然知道了这些检测方法,但如果elf文件被畸形不能静态分析(修复又是另外一回事了),也只能动态调试在这些关键API处下断点,也免不了掉坑调试崩溃,再来点指令混淆的话,调试起来确实比较恶心。虽然在Android平台同样也存在linux常用的ltrace(库函数trace)和strace(系统调用和信号trace)工具,但不能满足调试需求,还有检测ltrace的调试。废话不多说,直接进入正题(限于水平,难免会有疏漏和错误之处,请各位大大斧正,小弟感激不尽)。

二、  调用点trace
注入Hook API函数,当然首选zygote进程是最方便的了(如果zygote不能注入的话,那就关文档去修改ROM吧)。HooK住函数之后,通常采用下面这种模式添加代码:
Xxx new_fun(xxx){
  Before_call();
  Old_fun();
  After_call();
}
相信许多都知道ARM函数的调用流程,这里再啰嗦下 ARM汇编如何调用函数:
直接调用:BL/BLX  _xxfun
函数指针调用:BL/BLX  Rx
某些混淆代码:mov lr, [pc, #xx], 计算Rx,Ldr PC, Rx等
外部函数调用:BL/BLX _plt表项,plt表中load got表存在的函数地址到PC
被调函数一般模式:
Stmxx {Rx-Rx, lr}  /push

ldmxx {Rx-rx, pc}  /pop

函数的返回地址保存在lr寄存器中,之后被被调函数存在放栈上。只要lr的值未被修改,那么就保存着调用点的下一条指令地址!只要获取lr的值,那么就能跟踪到调用点。
知道了lr保存了调用点的值,获取lr的值也要注意时机。调用函数时lr的值已经被存在放栈上,修改lr也无关紧要。无法确定被调函数是否存在显式地给lr赋值或者函数调用,那要保证lr不被修改,故在函数入口点就保存lr的值是最佳也是最简单的选择。获取lr的值可以通过汇编来实现:
#define GETLR(store_lr)  \
  __asm__ __volatile__(  \
    "mov %0, lr\n\t"  \
    :  "=r"(store_lr)  \
  )
则Hook函数模式:
Xxx new_fun(xxx){
  Unsigned lr;
  GETLR(lr)
  Before_call();
  Old_fun();
  After_call();
}

来个实例,简单起见只Hook fopen函数:
FILE* new_fopen(const char *path,const char * mode){
  unsigned lr;
  GETLR(lr);

  if(strstr(path, "status") != NULL){
    LOGD("[*] Traced-fopen Call function: 0x%x\n", lr);
    if(strstr(path, "task") != NULL){
      LOGD("[*] Traced-anti-task/status");
    }else
      LOGD("[*] Traced-anti-status");
  }else if(strstr(path, "wchan") != NULL){
    LOGD("[*] Traced-fopen Call function: 0x%x\n", lr);
    LOGD("[*] Traced-anti-wchan");
  } 
  return old_fopen(path, mode);
}
注入后,某APK输出:
点击图片以查看大图

图片名称:	1.png
查看次数:	21
文件大小:	5.4 KB
文件 ID :	97242
图 1 调用点
Logcat:
 点击图片以查看大图

图片名称:	2.png
查看次数:	12
文件大小:	3.9 KB
文件 ID :	97243
图2  trace
Trace到了这个检测点,大概就知道这个函数想干什么了。动态调试时,也好准备”跨坑”而不是”掉坑”了。
除了直接获得这些调用点过坑外,还可以组合一些其他功能。比如监控APK启动时mmap分配内存,直接dd,便于大致分析某段代码做了什么,配合mprotect能起到一定的效果。当然,不必担心会监控到linker加载SO时mmap的无用信息,因为linker自身实现了mmap函数。
static void* new_mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset){
  unsigned lr;
  void* base = NULL;
  
  GETLR(lr);
  base = old_mmap(start, length, prot, flags, fd, offset);
  if((flags & MAP_ANONYMOUS) == 0){  //文件映射
    char file_name[256];
    char buf[256];
    memset(buf, 0, 256);
    sprintf(file_name, "/proc/self/fd/%d", fd);
    if(readlink(file_name, buf, 256) < 0){
      LOGD("[E] Traced-mmap --> readlink %s error\n", file_name);
      goto _done;
    }
    LOGD("[*] Traced-mmap --> [file] start = %p, length = 0x%x, filename = %s, offset = 0x%x", 
      start, length, buf, offset);
  }else{  //内存映射
    LOGD("[*] Traced-mmap --> [mem] start = %p, length = 0x%x", 
      start, length);
  }
  LOGD("[*] Traced-mmap Call function: 0x%x, Ret address: 0x%x\n", lr, (unsigned)base);
_done:
  return base;
}
点击图片以查看大图

图片名称:	3.png
查看次数:	11
文件大小:	4.1 KB
文件 ID :	97244
图 3
至于还能做什么,那就靠各位读者自行研究了吧。附上一些常见anti trace。

三、  Anti-anti
讨论一些常见的基于Hook的Anti-anti方法,欢迎讨论。
1、  status和stat
status和stat的Anti-anti方式类似,通过Hook fopen实现重定向到/data/local/tmp目录下:
sprintf(re_path, "/data/local/tmp/status");
if(!HasGenFile(re_path)){
  char buffer[BUFFERSIZE];
  FILE *fpr, *fpw;
  fpr = old_fopen(path, "r");
  fpw = old_fopen(re_path, "w");
  if(fpr == NULL || fpw == NULL){
    LOGD("[E] re-path [%s]failed", path);
    return old_fopen(path, mode);
  }
  while(fgets(buffer, BUFFERSIZE, fpr) != NULL){
    if(strstr(buffer, "State") != NULL){
      fputs("State:\tS (sleeping)\n", fpw);
    }
    if(strstr(buffer, "TracerPid") != NULL){
      fputs("TracerPid:\t0\n", fpw);
    }else{
      fputs(buffer, fpw);
    }
  }
  fclose(fpr);
  fclose(fpw);
}
2、  wchan
和status类似,只是重定向时,将等待事件设置为sys_epoll_wait:
if(strstr(path, "wchan") != NULL){
  LOGD("[*] Anti-anti-wchan!");
  strcpy(re_path, "data/local/tmp/wchan");
  if(!HasGenFile(re_path)){
    FILE *fpw;
    fpw = old_fopen(re_path, "w");
    if(fpw == NULL){
      LOGE("[E] re-path wchan failed!");
      goto __normal;
    }
    fputs("sys_epoll_wait", fpw);
    fclose(fpw);
  }
  return old_fopen(re_path, mode);

3、  inotify_add_watch
检测mem、pagemem、task等读取事件。可以直接让其返回-1,但不推荐这么做。如果检测代码并未对返回值做判断,直接使用,这样Anti-anti会导致程序崩溃,我的做法是改变mask的值:

//监控打开和读事件
if(strstr(pathname, "mem") != NULL){
  LOGD("[*] inotify_add_watch --> patch mem");
  return old_inotify_add_watch(fd, pathname, 0x00000200);    //mem永远不会被删除,改为0也可以
//监控打开和读事件,防获取反调试线程信息
}else if(strstr(pathname, "task") != NULL){
  LOGD("[*] inotify_add_watch --> patch task");
  return old_inotify_add_watch(fd, pathname, 0x00000200);  
4、  ptrace
这个函数算是用得比较多的吧,简单的检测代码是调用PTRACE_TRACEME,直接返回0就可以,不过现在这种方式很少了吧。某加固fork了进程去作ptrace,并写入一些数据。通过对ptrace hook,可以监控到写入数据。模拟这个通信过程就可以Anti-anti。具体就不展开了吧,相信各位读者可以做到了。
当然,还有一些Anti-anti方法,限于篇幅,就不展开了吧(让小弟学学各位大牛的Anti-anti方法吧)。

四、总结
做好Anti-trace和Anti-anti有些时候能大大节省时间,将精力专注于算法或者其他逻辑上。但也存在一些问题:
1、  HOOK检测
导出表HOOK检测:读取/system/lib/libc.so特定函数偏移,再获取本进程libc.so的基地址来检测是否有HOOK。(Patch方法:Hook fopen、dlopen和open函数)
Inline HooK检测:Inline Hook时要替换函数起始的字节码,可以检测一些比较奇怪的二进制码(BX pc等字节码)。
2、  LOGCAT
许多反调试都会起一个进程或者线程循环监控,此时anti-trace的输出会比较多,比如:
点击图片以查看大图

图片名称:	4.png
查看次数:	24
文件大小:	39.8 KB
文件 ID :	97245
图 4
这看起来比较烦,而且很多都是相同的。可以利用调用点trace地址的唯一性进行过滤,让同一信息只输出一次即可,也可以写个apk,将信息通过AF_UNIX本地套接字发送给apk,利用数据库的优势来存储等等。
3、  SVC
有些关键性的API,为了隐藏,直接通过汇编实现系统调用。ARM系统调用时的调用号通过r7寄存器来传递的。如果编写时,没有手写花指令,直接通过扫描SVC字节码和附近的关于r7的寄存器赋值操作,可以获得一些搜索结果。不过为了隐藏,手写点花指令也是可以的。
比如:常用来刷cache的代码
static void clearcache(char* begin, char *end)
{
  const int syscall = 0xf0002;
  __asm __volatile (
    "mov   r0, %0\n"
    "mov   r1, %1\n"
    "mov   r7, %2\n"
    "mov     r2, #0x0\n"
    "svc     0x00000000\n"
    :
    :  "r" (begin), "r" (end), "r" (syscall)
    :  "r0", "r1", "r7"
    );
}*转载请注明来自看雪论坛@PEdiy.com
上传的附件
文件类型: pdf 基于HOOK的Anti-debug callee检测和Anti-anti.pdf (359.8 KB, 578 次下载)
文件类型: zip trace_anti_debug.zip (1.71 MB, 848 次下载)
回复时引用此帖 返回顶端
共 18 位会员
感谢 ThomasKing 发表的文章:
acgmohu (2015-04-17), bengou (2015-04-16), cppasm (2015-04-16), deadxing (2015-11-20), Dormi (2015-04-18), Goly (2016-01-26), guxing罗 (2015-04-17), kllei (2015-05-18), Lnju (2015-04-18), piratelzs (2015-05-04), pregnant (2015-12-08), weslyw (2015-04-25), xiewukai (2016-03-27), zhzhlong (2015-05-15), 地狱怪客 (2015-12-23), 巅烽 (2015-04-16), 网络风尘 (2015-04-16), 雪衫 (2015-04-17)
mingxuan三千
级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时级别:28 | 在线时长:906小时 | 升级还需:51小时

mingxuan三千 的头像

初级会员
初级会员

资 料:
注册日期: May 2014
帖子: 140 mingxuan三千 品行端正
精华: 0
现金: 100 Kx
致谢数: 2
获感谢文章数:0
获会员感谢数:0
2 旧 2015-04-16, 21:28:29 默认
mingxuan三千 当前离线

感谢分享  学习了
回复时引用此帖 返回顶端
ShadoWWinL
级别:18 | 在线时长:399小时 | 升级还需:38小时级别:18 | 在线时长:399小时 | 升级还需:38小时级别:18 | 在线时长:399小时 | 升级还需:38小时

ShadoWWinL 的头像

初级会员
初级会员

资 料:
注册日期: May 2008
帖子: 57 ShadoWWinL 品行端正
精华: 0
现金: 252 Kx
致谢数: 1
获感谢文章数:0
获会员感谢数:0
3 旧 2015-04-16, 21:43:33 默认
ShadoWWinL 当前离线

入门还是不错的。。。
回复时引用此帖 返回顶端
我是小三
级别:28 | 在线时长:898小时 | 升级还需:59小时级别:28 | 在线时长:898小时 | 升级还需:59小时级别:28 | 在线时长:898小时 | 升级还需:59小时级别:28 | 在线时长:898小时 | 升级还需:59小时

我是小三 的头像

普通会员
普通会员

资 料:
注册日期: Jul 2012
帖子: 102 我是小三 品行端正
精华: 3
现金: 178 Kx
致谢数: 4
获感谢文章数:13
获会员感谢数:71
4 旧 2015-04-16, 22:00:20 默认
我是小三 当前离线

来学习的,多谢分享。
回复时引用此帖 返回顶端
peterchen
级别:20 | 在线时长:510小时 | 升级还需:15小时级别:20 | 在线时长:510小时 | 升级还需:15小时

初级会员
初级会员

资 料:
注册日期: May 2004
帖子: 198 peterchen 品行端正
精华: 0
现金: 294 Kx
致谢数: 0
获感谢文章数:1
获会员感谢数:5
5 旧 2015-04-17, 09:36:55 icon14
peterchen 当前离线

TK牛很nice,技术也nice... 
最近都有撤贴风,马上本地备份一份
回复时引用此帖 返回顶端
wangzehua
级别:13 | 在线时长:243小时 | 升级还需:9小时级别:13 | 在线时长:243小时 | 升级还需:9小时级别:13 | 在线时长:243小时 | 升级还需:9小时级别:13 | 在线时长:243小时 | 升级还需:9小时

wangzehua 的头像

初级会员
初级会员

资 料:
注册日期: Oct 2010
帖子: 37 wangzehua 品行端正
精华: 0
现金: 100 Kx
致谢数: 0
获感谢文章数:0
获会员感谢数:0
6 旧 2015-04-17, 09:55:29 默认
wangzehua 当前离线

好东西,支持一个
回复时引用此帖 返回顶端
鬼谷子c
级别:13 | 在线时长:237小时 | 升级还需:15小时级别:13 | 在线时长:237小时 | 升级还需:15小时级别:13 | 在线时长:237小时 | 升级还需:15小时级别:13 | 在线时长:237小时 | 升级还需:15小时

鬼谷子c 的头像

普通会员
普通会员

资 料:
注册日期: Aug 2010
帖子: 244 鬼谷子c 品行端正
精华: 1
现金: 6 Kx
致谢数: 22
获感谢文章数:5
获会员感谢数:18
7 旧 2015-04-17, 10:03:04 默认
鬼谷子c 当前离线

前排顶一顶,好资料,感谢分享~~~~~这个是substrate来做的hook,还是自己实现的框架呢?
回复时引用此帖 返回顶端
ThomasKing
级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时级别:13 | 在线时长:246小时 | 升级还需:6小时

ThomasKing 的头像

普通会员
普通会员

资 料:
注册日期: Apr 2014
帖子: 196 ThomasKing 品行端正
精华: 7
现金: 228 Kx
致谢数: 4
获感谢文章数:19
获会员感谢数:282
8 旧 2015-04-17, 10:04:35 默认
ThomasKing 当前离线

引用:
最初由 鬼谷子c发布 查看帖子
前排顶一顶,好资料,感谢分享~~~~~这个是substrate来做的hook,还是自己实现的框架呢?
鬼哥,上次实现的Hook库
回复时引用此帖 返回顶端
cacorothuo
级别:17 | 在线时长:359小时 | 升级还需:37小时级别:17 | 在线时长:359小时 | 升级还需:37小时

cacorothuo 的头像

初级会员
初级会员

资 料:
注册日期: Oct 2011
帖子: 146 cacorothuo 品行端正
精华: 0
现金: 100 Kx
致谢数: 6
获感谢文章数:6
获会员感谢数:18
9 旧 2015-04-17, 10:22:55 默认
cacorothuo 当前离线

现在已经工作了吗。还是在某地实习。
回复时引用此帖 返回顶端
OnlyEnd
级别:26 | 在线时长:796小时 | 升级还需:41小时级别:26 | 在线时长:796小时 | 升级还需:41小时级别:26 | 在线时长:796小时 | 升级还需:41小时级别:26 | 在线时长:796小时 | 升级还需:41小时级别:26 | 在线时长:796小时 | 升级还需:41小时

OnlyEnd 的头像

初级会员
初级会员

资 料:
注册日期: Oct 2012
帖子: 147 OnlyEnd 品行端正
精华: 0
现金: 48 Kx
致谢数: 10
获感谢文章数:0
获会员感谢数:0
10 旧 2015-04-17, 10:24:51 默认
OnlyEnd 当前离线

我用substrate做了个过这些反调试的。  远远没有你这个这么强大呀 哈哈哈  学习学习
回复时引用此帖 返回顶端
vVv一
级别:6 | 在线时长:65小时 | 升级还需:12小时级别:6 | 在线时长:65小时 | 升级还需:12小时级别:6 | 在线时长:65小时 | 升级还需:12小时

vVv一 的头像

初级会员
初级会员

资 料:
注册日期: Aug 2014
帖子: 29 vVv一 品行端正
精华: 0
现金: 77 Kx
致谢数: 0
获感谢文章数:0
获会员感谢数:0
11 旧 2015-04-17, 13:50:48 默认
vVv一 当前离线

学习一下,感谢分享~
回复时引用此帖 返回顶端
guxing罗
级别:11 | 在线时长:173小时 | 升级还需:19小时级别:11 | 在线时长:173小时 | 升级还需:19小时级别:11 | 在线时长:173小时 | 升级还需:19小时级别:11 | 在线时长:173小时 | 升级还需:19小时级别:11 | 在线时长:173小时 | 升级还需:19小时

guxing罗 的头像

初级会员
初级会员

资 料:
注册日期: Apr 2012
帖子: 126 guxing罗 品行端正
精华: 0
现金: 36 Kx
致谢数: 16
获感谢文章数:0
获会员感谢数:0
12 旧 2015-04-17, 15:49:52 默认
guxing罗 当前离线

居然是。。。支持大牛。。。。。。。。。。。
回复时引用此帖 返回顶端
wule
级别:9 | 在线时长:119小时 | 升级还需:21小时级别:9 | 在线时长:119小时 | 升级还需:21小时级别:9 | 在线时长:119小时 | 升级还需:21小时

初级会员
初级会员

资 料:
注册日期: Mar 2013
帖子: 63 wule 品行端正
精华: 0
现金: 8 Kx
致谢数: 4
获感谢文章数:1
获会员感谢数:1
13 旧 2015-04-18, 12:39:37 默认
wule 当前离线

火速围观。楼主真好人。
回复时引用此帖 返回顶端
ztxb
级别:7 | 在线时长:80小时 | 升级还需:16小时级别:7 | 在线时长:80小时 | 升级还需:16小时级别:7 | 在线时长:80小时 | 升级还需:16小时级别:7 | 在线时长:80小时 | 升级还需:16小时

初级会员
初级会员

资 料:
注册日期: Dec 2007
帖子: 42 ztxb 品行端正
精华: 0
现金: 217 Kx
致谢数: 10
获感谢文章数:0
获会员感谢数:0
14 旧 2015-04-20, 01:28:06 默认
ztxb 当前离线

感谢楼主分享.下载研究研究.
回复时引用此帖 返回顶端
deadxing
级别:5 | 在线时长:59小时 | 升级还需:1小时级别:5 | 在线时长:59小时 | 升级还需:1小时

deadxing 的头像

初级会员
初级会员

资 料:
注册日期: Sep 2012
帖子: 74 deadxing 品行端正
精华: 0
现金: 7 Kx
致谢数: 31
获感谢文章数:0
获会员感谢数:0
15 旧 2015-06-02, 09:25:49 默认
deadxing 当前离线

tk
是tk教主么。。哈哈
回复时引用此帖 返回顶端
发表新主题 回复

添加到书签

主题工具
显示模式

发帖规则
不可以发表主题
不可以回复帖子
不可以上传附件
不可以编辑自己的帖子
论坛论坛启用 vB 代码
论坛启用 表情图标

相似的主题
主题 主题作者 论坛 回复 最后发表
调试逆向 【原创】Anti StrongOD Kernel Mode 半斤八兩 『软件调试逆向』 20 2014-11-01 00:40:34
【原创】Anti SSDT Hook 认真的雪 『编程技术』 39 2012-01-20 16:12:17
调试逆向 【原创】小试 anti vmware 天易love 『软件调试逆向』 38 2011-01-20 08:12:49
【原创】anti wmware dummy 『软件调试逆向』 18 2007-05-02 16:24:29


所有时间均为北京时间, 现在的时间是 00:59:38.


  ©2000-2016 看雪学院(PEdiy.com) |关于我们 | 京ICP备10040895号-17 | 知道创宇提供带宽资源 | 微信公众帐号:ikanxue