通过inotify实现反调试


1.inotify

linux下inotify可以实现监控文件系统事件(打开,读写删除等),inotify最常见的api有以下几个:

  • inotify_init:用于创建一个 inotify 实例的系统调用,并返回一个指向该实例的文件描述符。
  • inotify_add_watch:增加对文件或者目录的监控,并指定需要监控哪些事件。
  • read:读取包含一个或者多个事件信息的缓存。
  • inotify_rm_watch:从监控列表中移出监控项目。

inotify_add_watch原型如下:

 int inotify_add_watch(int fd, const char* pathname, int mask)
  • 第一个参数fd是inotify_init的返回值。
  • 第二个参数是要监控的文件目录。
  • 第三个参数表示要监控哪些事件。

inotify的mask类型具体定义见:linux-3.18.6/include/uapi/linux/inotify.h#29

从read函数读出的内容是多个 inotify_event 结构体,该结构体定义如下:

每个触发的事件都对应了一个inotify_event结构体,只要判断这个结构体中的mask是否为指定的事件(open,read等)即可判断这个发生的事件是否对我们有用。

2.select函数

select系统调用是用来让我们的程序监视多个文件句柄的状态变化,select函数原型及参数说明如下:

  • 参数maxfd是需要监视的最大的文件描述符值+1;
  • rdset,wrset,exset分别对应于需要检测的可读文件描述符的集合,可写文件描述符的集合及异常文件描述符的集合。
  • struct timeval结构用于描述一段时间长度,如果在这个时间内,需要监视的描述符没有事件发生则函数返回,返回值为0。

3.通过inotify实现反调试

通过inotify监控/proc/pid文件夹下的关键文件变化(maps的读,mem的读等),若想查看某进程的的虚拟地址空间或者想dump内存,则会触发打开或读取的事件,只要接收到这些事件,则说明进程正在被调试,直接kill主进程。主要代码如下:

//fork子进程调用该函数,并且传入父进程pid
void AntiDebug ( int ppid ) {
 
char buf [ 1024 ] , readbuf [ MAXLEN ] ;
int pid , wd , ret , len , i ;
int fd ;
fd_set readfds ;
//防止调试子进程
ptrace ( PTRACE_TRACEME , 0 , 0 , 0 ) ;
fd =    inotify_init ( ) ;
sprintf ( buf , "/proc/%d/maps" , ppid ) ;
 
//wd = inotify_add_watch(fd, "/proc/self/mem", IN_ALL_EVENTS);
wd = inotify_add_watch ( fd , buf , IN_ALL_EVENTS ) ;
if ( wd < 0 ) {
LOGD ( "can't watch %s" , buf ) ;
return ;
}
while ( 1 ) {
i = 0 ;
                 //注意要对fd_set进行初始化
FD_ZERO ( & readfds ) ;
FD_SET ( fd , & readfds ) ;
                 //第一个参数固定要+1,第二个参数是读的fdset,第三个是写的fdset,最后一个是等待的时间
                 //最后一个为NULL则为阻塞
ret = select ( fd + 1 , & readfds , 0 , 0 , 0 ) ;
if ( ret == - 1 )
break ;
if ( ret ) {
len = read ( fd , readbuf , MAXLEN ) ;
while ( i < len ) {
                                 //返回的buf中可能存了多个inotify_event
struct inotify_event * event = ( struct inotify_event* ) & readbuf [ i ] ;
LOGD ( "event mask %d\n" , ( event -> mask & IN_ACCESS ) || ( event -> mask & IN_OPEN ) ) ;
                                 //这里监控读和打开事件
if ( ( event -> mask & IN_ACCESS ) || ( event -> mask & IN_OPEN ) ) {
LOGD ( "kill!!!!!\n" ) ;
                                                 //事件出现则杀死父进程
int ret = kill ( ppid , SIGKILL ) ;
LOGD ( "ret = %d" , ret ) ;
return ;
}
i += sizeof ( struct inotify_event ) + event -> len ;
}
}
}
inotify_rm_watch ( fd , wd ) ;
close ( fd ) ;
}


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM