利用Java实现WebShell特征码定位器(一)

2014-11-23 23:56:48 · 作者: · 浏览: 0

文/图 海啸天鸣(Ansty) [华南农业大学 李海鸣]
不知大家是否还记得我去年在黑防发表的一篇有关WebShell特征码定位方法的文章,在那篇文章里,WebShell的特征码我是采用手工定位的,手工定位不仅效率低下,而且消磨了我们的免杀积极性。因此,我们有必要利用工具来实现自动化操作。下面,我们就利用Java自己编写一个WebShell特征码定位器。如图1所示就是我们要实现的WebShell特征码定位器。

图1
因为WebShell一般都不会很大,所以我们可以一次删除WebShell一行代码并保存文件,这样,在抽取出了WebShell的每一行代码后,就会生成很多的WebShell文件,然后我们用杀软对生成的文件进行杀毒,剩下的文件就是我们抽取了WebShell特征码以后的WebShell了。最后统计一下杀毒剩下的文件,就可以得到特征码是存在哪一行或者哪些行代码里面了。
下面我们一起来看看程序的实现,至于GUI的设计,我就不介绍了,这个不是我们的重点。在正式开始之前,先来看看全局变量的声明。

private JButton jbSelect; //文件选择按钮
private JButton jbAna; //开始分析按钮
private JButton jbLocate; //定位按钮
private JTextArea jtaResult; //结果显示文本域
private JTextArea jtaHelp; //帮助文本域
private JTextField jtfFile; //文件路径框
private File shell; //webshell选择文件
private String path; //文件父目录
private String fileExt; //文件扩展名
private Vector fileContent; //文件内容,向量

1) 得到用户选择的WebShell文件

private void chooseFile(){
int choice;
JFileChooser jfc = new JFileChooser();
//使用JDK提供的JFileChooser类获得一个文件选择对话框
jfc.setSize(400,400);
choice = jfc.showOpenDialog(this);
//JFileChooser这个类提供了“保存文件、打开文件”等模式,这里我们使用“打开文件”模式,showOpenDialog用于显示一个文件打开对话框
if(choice == JFileChooser.APPROVE_OPTION){
//选择确认(yes、ok)后返回该值。
shell = jfc.getSelectedFile();
//getSelectedFile这个方法会返回一个File对象,也就是我们选择的文件了
jtfFile.setText(shell.getAbsolutePath());
//使用file对象的getAbsolutePath方法得到文件的路径
fileExt = shell.getName().substring(shell.getName().lastIndexOf("."));
//得到文件的扩展名,最后一个“.”号后面的就是文件的扩展名了。Substring这个方法的功能就是从指定位置开始截取字符串
jbAna.setEnabled(true);
}
}

2)读取WebShell文件内容(readFile())
选择好WebShell后,我们就要开始分析抽取了。为了提高读取效率,我们将WebShell全部读入到内存并保存到Vector里面,方便进行查找。

BufferedReader br;
br = new BufferedReader(new InputStreamReader(new FileInputStream(shell)));
//使用带缓存的方法来读取文件
String temp; //存放每一行数据的临时变量
while ((temp = br.readLine()) != null) {
//当文件读到最后一行的时候返回的是null,以此来作为循环结束条件
fileContent.add(temp);
//按行将文件内容存入Vector fileContent
}

在这里,如果程序正常执行完以后,WebShell的内容将会全部存到fileContent变量里。

3)批量保存抽取代码后的WebShell(writeFile())
在我们的writeFile()方法执行前,“path=shell.getParent()+"\"+"temp"+"\";”这句代码是要在WebShell的同一目录下新建一个temp文件夹来保存生成的临时文件。

PrintWriter pw; //使用printwriter输出到文件
try {
File dir = new File(this.path);
dir.mkdir(); //在WebShell目录下新建一个temp文件夹
for(int i=0;i//每个文件抽一行代码,循环整个文件
String path = this.path + (i+1) + fileExt;
//得到我们要保存的文件路径,每一个文件用所抽取代码的所在行数来命名,扩展名用原WebShell的扩展名
pw = new PrintWriter(new OutputStreamWriter(new FileOutputStream(path)),true);
//建立输出到文件的连接
for(int j=0;jif(j!=i) //因为当前文件是按行号来命名的,而文件名就恰好是我们要抽取的代码,当我们的行号等于当前文件号的时候,就跳过该行,不做输出,那么就实现抽取代码的功能了
pw.println(fileContent.get(j)); //按行输出到文件
}
pw.close(); //每个文件输出完成后一定要关闭文件输出流
}

4) 杀毒
这一步就没什么好说了,用杀毒软件将生成的文件进行杀毒,发现病毒就直接删除,剩下没被杀掉的就是已经抽取了特征码的WebShell了。这个时候的Webshell虽然是杀软抓不到了,但它不是完整的,因为我们已经将它的部分代码抽取掉了,而且我们也不知道那些代码的功能,所以还需要下面一步的定位。

5) 定位(locate())
定位的思路就是分析杀毒剩下的WebShell。刚才说过了,我们的文件命名是用抽取代码所在的行号实现的,那么剩下的那些文件的文件名,就是我们特征码的所在的行号了。

File result = new File(shell.getParent()+"\temp");
//得到temp的目录
boolean[] exist = new boolean[fileContent.size()];
//存储文件是否存在,boolean初始化的时候自动是false
String[] dirContent = result.list();
//得到当前目录下所有文件,list()方法返回String[]
int temp;
for(int i=0;i//循环检查目录下面的文件
temp = Integer.parseInt(dirContent[i].substring(0,dirContent[i].lastIndexOf(".")));
//dirContent[i].lastIndesOf(“.”)得到扩展名的在文件名中