反调试的方法很多,不过由于android系统是开源的,所以反调试其实也不是很神秘的东西。 下面是常见的也是很多厂商都在使用,包括我们项目组也在使用的。多个方案相互结合可以实现更好反调试。
1.1 ptrace自己,使得android_server附加不上
1void anti_ptrace() 2{ 3ptrace(PTRACE_TRACEME, 0, 0, 0); 4} 5
1.2. 检测Tracepid的值
1void anti_Tracepid() 2{ 3try 4{ 5const int bufsize = 1024; 6char filename[bufsize]; 7char line[bufsize]; 8int pid = getpid(); 9sprintf(filename, “/proc/%d/status”, pid); 10FILE* fd = fopen(filename, “r”); 11if (fd !=NULL) 12{ 13while (fgets(line, bufsize, fd)) 14{ 15if (strncmp(line, “TracerPid”, 9) == 0) 16{ 17int statue = atoi(&line[10]); 18if (statue != 0) 19{ 20fclose(fd); 21int ret = kill(pid, SIGKILL); 22} 23break; 24} 25} 26fclose(fd); 27} else 28{ 29// LOGD(“open %s fail…”, filename); 30} 31} catch (…) 32{ 33 34} 35 36} 37
1.3 检测端口号,针对android_server这个端口号
1void anti_serverport() { 2const int bufsize=512; 3char filename[bufsize]; 4char line[bufsize]; 5int pid =getpid(); 6sprintf(filename,"/proc/net/tcp"); 7FILE* fd=fopen(filename,“r”); 8if(fd!=NULL){ 9while(fgets(line,bufsize,fd)){ 10if (strncmp(line, “5D8A”, 4)==0){ 11int ret = kill(pid, SIGKILL); 12} 13} 14} 15fclose(fd); 16 17} 18
1.4 检测这些调试进程的名字
1void anti_processstatus(){ 2const int bufsize = 1024; 3char filename[bufsize]; 4char line[bufsize]; 5char name[bufsize]; 6char nameline[bufsize]; 7int pid = getpid(); 8//先读取Tracepid的值 9sprintf(filename, “/proc/%d/status”, pid); 10FILE *fd=fopen(filename,“r”); 11if(fd!=NULL){ 12while(fgets(line,bufsize,fd)){ 13if(strstr(line,“TracerPid”)!=NULL) 14{ 15int statue =atoi(&line[10]); 16if(statue!=0){ 17sprintf(name,"/proc/%d/cmdline",statue); 18FILE *fdname=fopen(name,“r”); 19if(fdname!= NULL){ 20while(fgets(nameline,bufsize,fdname)){ 21if(strstr(nameline,“android_server”)!=NULL){ 22int ret=kill(pid,SIGKILL); 23} 24} 25} 26fclose(fdname); 27} 28} 29} 30} 31fclose(fd); 32} 33
1.5. 检测常放目录:/data/local/tmp
1void anti_localtmp(){ 2int pid=getpid(); 3const int bufsize=1024; 4char line[bufsize]; 5char filename[bufsize]; 6sprintf(filename,"/data/local/tmp"); 7FILE *fd=fopen(filename,“r”); 8if(fd!=NULL){ 9while(fgets(line,bufsize,fd)){ 10if(strstr(line,“android_server”)!=NULL){ 11int ret=kill(pid,SIGKILL); 12} 13} 14} 15fclose(fd); 16} 17
1.6 检测break point指令
1unsigned long GetLibAddr() { 2unsigned long ret = 0; 3char name[] = “libptrace.so”; 4char buf[4096], *temp; 5int pid; 6FILE *fp; 7pid = getpid(); 8sprintf(buf, “/proc/%d/maps”, pid); 9fp = fopen(buf, “r”); 10if (fp == NULL) { 11puts(“open failed”); 12goto _error; 13} 14while (fgets(buf, sizeof(buf), fp)) { 15if (strstr(buf, name)) { 16temp = strtok(buf, “-”); 17ret = strtoul(temp, NULL, 16); 18break; 19} 20} 21_error: fclose(fp); 22return ret; 23} 24
1.7 通过使用Linux inotify特性来对文件的读写,以及打开等权限进行监控
1void anti_debug06() { 2int ret, len, i; 3int pid6 = getpid(); 4const int MAXLEN = 2048; 5char buf[1024]; 6char readbuf[MAXLEN]; 7int fd, wd; 8fd_set readfds; 9fd = inotify_init(); 10sprintf(buf, “/proc/%d/maps”, pid6); 11wd = inotify_add_watch(fd, buf, IN_ALL_EVENTS); 12if(wd>=0){ 13while (1) { 14i = 0; 15FD_ZERO(&readfds);//使得readfds清零 16FD_SET(fd, &readfds);//将fd加入readfds集合 17ret = select(fd + 1, &readfds, 0, 0, 0); 18if(ret==-1){ 19break; 20} 21if (ret) { 22len = read(fd, readbuf, MAXLEN); 23while (i < len) { 24struct inotify_event *event = (struct inotify_event *) &readbuf[i]; 25if ((event->mask & IN_ACCESS) || (event->mask & IN_OPEN)) { 26int ret = kill(pid6, SIGKILL); 27return; 28} 29i += sizeof(struct inotify_event) + event->len; 30} 31} 32 33} 34} 35inotify_rm_watch(fd, wd); 36close(fd); 37 38} 39
1.8.检测被调试代码的前后时间的差异;
1int gettimeofday(struct timeval *tv,struct timezone *tz); 2void anti_debug07(){ 3int pid=getpid(); 4struct timeval t1; 5struct timeval t2; 6struct timezone tz; 7gettimeofday(&t1,&tz); 8gettimeofday(&t2,&tz); 9// int timeoff=gettimeofday(&t1,0)-gettimeofday(&t2,0); 10int timeoff=(t2.tv_sec)-(t1.tv_sec); 11if(timeoff>1){ 12int ret=kill(pid,SIGKILL); 13return ; 14} 15} 16 17
更多安全技术文章,请关注 “小道安全”公众号,一起交流,一起进步。