参考网上的脚本做了一些小的修改。

原理是利用pyinotify库实现文件监控,在EventHandler类的各个方法中调用一些自定义的方法来实现个人定制的文件监控功能,具体的可参考官方文档。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
import os
import argparse
import hashlib
from pyinotify import WatchManager, Notifier,ProcessEvent
from pyinotify import IN_DELETE, IN_CREATE, IN_MOVED_TO, IN_ATTRIB, IN_MODIFY

dir_path = ""

class EventHandler(ProcessEvent):
"""事件处理"""
#创建新文件,自动删除
def process_IN_CREATE(self, event):
print "[!] Create : " + event.pathname
DeleteFileOrDir(event.pathname)

#文件被删除,如rm命令,自动恢复原文件
def process_IN_DELETE(self, event):
print "[!] Delete : " + event.pathname
# CanNotDel(event.pathname)

#文件属性被修改,如chmod、chown命令
def process_IN_ATTRIB(self, event):
print "[!] Attribute been modified:" + event.pathname

#文件被移来,如mv、cp命令,自动删除
def process_IN_MOVED_TO(self, event):
print "[!] File or dir been moved to here: " + event.pathname
DeleteFileOrDir(event.pathname)

#文件被修改,如vm、echo命令,自动恢复原文件
def process_IN_MODIFY(self, event):
print "[!] Modify : " + event.pathname
CanNotModify(event.pathname)

def DeleteFileOrDir(target):
if os.path.isdir(target):
fileslist = os.listdir(target)
try:
os.system('cp ' + str(target) + ' /tmp/evil_files/')
except:
pass
for files in fileslist:
DeleteFileOrDir(target + "/" + files)
try:
os.rmdir(target)
print " >>> Delete directory successfully: " + target
except:
print " [-] Delete directory failed: " + target
if os.path.isfile(target):
try:
os.system('cp ' + str(target) + ' /tmp/evil_files/')
except:
pass
try:
os.remove(target)
print " >>> Delete file successfully" + target
except:
print " [-] Delete file failed: " + target

def get_file_md5(f):
m = hashlib.md5()
while True:
#如果不用二进制打开文件,则需要先编码
#data = f.read(1024).encode('utf-8')
data = f.read(1024) #将文件分块读取
if not data:
break
m.update(data)
return m.hexdigest()

def CompareFile(file1, file2):
with open(file1, 'rb') as f1, open(file2, 'rb') as f2:
file1_md5 = get_file_md5(f1)
file2_md5 = get_file_md5(f2)

if file1_md5 != file2_md5:
return True
else:
return False

def CanNotModify(target):
if os.path.exists(target):
if os.path.isfile(target):
print "dir path: " + dir_path
target_new = "/tmp/backup/" + str(target).split(dir_path)[1]
isChanged = CompareFile(str(target), target_new)
if isChanged:
try:
os.system('cp ' + str(target) + ' /tmp/evil_files/')
except Exception, e:
pass
try:
os.system("cat " + target_new + " > " + str(target))
print " >>> Recover file successfully"
except Exception, e:
print " [-] Recover file failed: " + target

def CanNotDel(target):
if not os.path.exists(target):
try:
target_new = "/tmp/backup/" + str(target).split(dir_path)[1]
os.system("cat " + target_new + " > " + str(target))
print " >>> Recover file successfully"
except Exception, e:
print " [-] Recover file failed: " + target

def Monitor(path):
wm = WatchManager()
mask = IN_DELETE | IN_CREATE | IN_MOVED_TO | IN_ATTRIB | IN_MODIFY
notifier = Notifier(wm, EventHandler())
wm.add_watch(path, mask,rec=True)
print '[+] Now Starting Monitor: %s'%(path)
while True:
try:
notifier.process_events()
if notifier.check_events():
notifier.read_events()
except KeyboardInterrupt:
notifier.stop()
break

if __name__ == "__main__":
try:
os.system('mkdir /tmp/evil_files/')
os.system('mkdir /tmp/backup/')
except:
print 'Oh.'
parser = argparse.ArgumentParser(
usage="%(prog)s -w [path]",
description=('''
Introduce:Simple Directory Monitor! by ssooking''')
)
parser.add_argument('-w','--watch',action="store",dest="path",default="/var/www/html/",help="directory to watch,default is /var/www/html")
args=parser.parse_args()
dir_path = str(args.path)
print "dir path: " + dir_path
cmd = 'cp -r ' + str(args.path)
print "dir path: " + dir_path
cmd = 'cp -r ' + str(args.path) + '* /tmp/backup/'
os.system(cmd)
Monitor(args.path)

代码的功能应该一目了然。

有个问题,AWD实际情况中未必有pyinotify这个库或者根本没有Python环境,一种解决方案是自己准备好Python和pyinotify库的源码安装包。

除此之外,我们可以将Python文件提前编译成32位和64位的ELF文件,即到即用就OK了。

这里用到一个名为pyinstaller的库,安装很简单:pip install pyinstaller

使用也很简单:pyinstaller -F ./Monitor.py

编译完成后,在dist子目录中可以找到目标可执行文件。

注意:pyinstaller在不用系统环境编译出来的可执行文件是存在区别,在Windows上编译生成的是EXE文件,在Linux上编译生成的是ELF文件,而在32位系统才会生成32位可执行文件、在64位系统生成64位可执行文件。