通常,运维人员会在系统上安装杀毒软件,用来做病毒防护。其实病毒最基本的特征是对文件系统的部分或则全部做了改动,假如我们开发这样一个程序,定时对文件系统的改动进行计算,定期或不定期生成报告或发送告警信息,也一样可以实现防病毒功能,主要可以用来检测系统是否被改动过。
这个功能类似Linux系统上一款比较著名的软件tripwire ,用来检测Linux的文件系统是否被改动过,还可以定期生成报告
用Java来实现的话,首先想到的就是并行检测,那么肯定需要多个线程同时工作,提高检测效率,同时把完整的检测结果存档,加密,作为下一次的比对标准。存档的东西需要定期更新,而且要备份,这个要注意。
检测文件是否被改动,方法有很多,比较简单的是看文件的组后修改日期,还有就是计算文件的Hash值
部分实现:
public class CheckTimerTask extends TimerTask {
public static Logger logger = Logger.getLogger(CheckTimerTask.class.getName());
private String md5FilePath;
private FileHandler fileHandler = new FileHandler();
public CheckTimerTask(String md5FilePath) {
this.md5FilePath = md5FilePath;
}
public void run() {
boolean flag = false;
PropertiesConfig p = new PropertiesConfig();
// 配置文件的MD5
String configFileMd5 = p.getMd5FileMd5();
logger.info("configFileMd5:"+configFileMd5);
String configMd5 = null;
// 实际算出来的MD5
configMd5 = GetMD5Value.getMd5ByFile(md5FilePath);
if ("".equals(configMd5)) {
logger.warn(configMd5 + " not exist!");
}
if (!configFileMd5.equals(configMd5)) {
flag = true;
DbHandler.saveAttack(md5FilePath, configFileMd5, configMd5, "appmd5文件MD5改变");
logger.info(md5FilePath + " has changed!");
}
Map map = fileHandler.readMd5File(md5FilePath);
String appFilePath = PropertiesConfig.userHome + "config" + File.separator + "appname";
HashMap appMap = fileHandler.readEncoderAppFile(appFilePath);
Iterator it = map.keySet().iterator();
String fileName = null;
String fileMd5 = null;
String appMd5 = null;
while (it.hasNext()) {
fileName = (String) it.next();
HashMap valueMap = (HashMap)appMap.get(fileName);
fileMd5 = (String) map.get(fileName);
File file = new File(fileName);
StringBuffer sbFile = new StringBuffer();
if (file.isDirectory()) {
// 文件夹
List list = new ArrayList();
list = fileHandler.showAllFilesExclude(list, file, valueMap);
Collections.sort(list);
for (int j = 0; j < list.size(); j++) {
sbFile.append(GetMD5Value.getMd5ByFile((String) list.get(j)));
}
try {
appMd5 = GetMD5Value.getMd5ByString(sbFile.toString());
} catch (Exception e) {
e.printStackTrace();
}
} else if (file.isFile()) {
// 文件
appMd5 = GetMD5Value.getMd5ByFile(fileName);
} else {
appMd5 = GetMD5Value.getMd5ByFile(fileName);
}
if (!fileMd5.equals(appMd5)) {
// 写入攻击事件,修改文件
flag = true;
DbHandler.saveAttack(fileName, fileMd5, appMd5, "应用程序MD5改变");
logger.info(fileName + " has changed!");
}
}
if (flag) {
// MD5发生变更,重新生成
fileHandler.encoderFile();
configMd5 = GetMD5Value.getMd5ByFile(md5FilePath);
if (configMd5 != null)
PropertiesConfig.updateMd5(configMd5);
}
}
在实现的过程中,可以排除一些指定目录(比如日志目录等),把监控到的异常记录到日志,经过报警系统发现报警信息,同时,周期性的生产报告,发送到管理员。
这样的程序一般都需要有守护进程,用来监控该功能是否被恶意Kill掉,所以在实现的过程中,还需要实现一个Monitor进程。