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
)
;
}