朋友U盘感染了病毒,文档都被杀毒软件kill了,
“邹小朋爱邹琪”Word文档病毒修复病毒防范
。数据恢复后打开都是乱码,让我帮忙看下。于是对U盘进行了数据恢复,在恢复的文件中发现每个word文档都多了一个一样大的同名exe文件,而原doc文件打开后显示乱码,执行exe文件可以正常打开doc文件。应该是病毒对文档进行了修改,exe文件的功能则是逆向修改并打开。
用编辑器打开word文档,发现第一行有几个可读字符“邹小朋爱邹琪”,估计是哪个恶作剧的病毒留下的。百度之,果然是这种病毒。
此类病毒会篡改用户电脑后缀名为doc的word文档的DOC头,同时隐藏原始doc文件,并且创建一个同名的exe来启动被篡改以后的doc文档。这个exe会在内存中修复doc头,因此使用这个exe文件加载的doc文档可以正常显示内容。一旦病毒体被安全软件查杀,此时用户打开doc文档会发现是乱码,当然可以正常显示出来的内容是“邹小朋爱邹琪”
知道了原因就好办了。新建一个word文档,随便写几个字。用winhex打开正常文档和损坏文档对比发现文件头里,前十二个字节有差异。
损坏:D7 DE D0 A1 C5 F3 B0 AE D7 DE E7 F7
正常:D0 CF 11 E0 A1 B1 1A E1 00 00 00 00
修复就很简单了,将损坏的文件头改回去就行了。
写了个批量修复的工具,源码如下:
publicclassRepair{
//遍历、检测目标目录
voiddetect(Stringpath) {
Filebroken=newFile(path);
String[] files=null;// 损坏的文件名列表
if (broken.isDirectory()) {
files=broken.list();
for (Stringfile : files) {
detect(path+File.separator+file);
}
}else{
if ("doc".equals(path.substring(path.length()-3, path.length())))
{
try{
startRepair(broken);
} catch (FileNotFoundExceptione) {
e.printStackTrace();
}
}
}
}
//对比特征文件头检测文件是否损坏
voidstartRepair(Filesingle)throwsFileNotFoundException{
int[] head=newint[3];// 特征文件头
StringheadString="";// 特征文件头
DataInputStreamis=newDataInputStream(newFileInputStream(single));
try{
for(inti : head) {
i=is.readInt();
headString+=Integer.toHexString(i);
}
}catch(IOExceptione) {
System.out.println(single+" is doubt");
e.printStackTrace();
}finally{
try{
is.close();
}catch(IOExceptione) {
e.printStackTrace();
}
}
//匹配特征字符串
if (headString.equals("d7ded0a1c5f3b0aed7dee7f7")) {
System.out.println(single+" is broken");
modify(single);
}else{
System.out.println(single+" is ok");
}
}
//使用正常的文件头修复损坏的文件
voidmodify(Filefile) {
try{
FiletempFile=newFile(file.getAbsolutePath()+"(修复后).doc");
InputStreamis=newBufferedInputStream(newFileInputStream(file));
OutputStreamos=newBufferedOutputStream(newFileOutputStream(tempFile));
// 正常的文件头
byte[] goodHead={ (byte)0xd0, (byte)0xcf, (byte)0x11,
(byte)0xe0, (byte)0xa1, (byte)0xb1, (byte)0x1a,
(byte)0xe1, (byte)0x00, (byte)0x00, (byte)0x00,
(byte)0x00};
byte[] buf=newbyte[1024];
intlen=0;
// 先处理前12个字节
os.write(goodHead);
is.read(buf,0,12);
// 复制后面的内容
while (-1!=(len=is.read(buf,0, buf.length))) {
os.write(buf);
}
is.close();
os.close();
}catch(IOExceptione) {
e.printStackTrace();
}
System.out.println(file+" already repaired!");
}
publicstaticvoidmain(String[] args) {
Repairr=newRepair();
//检测c:/source下的所有文件
r.detect("c:/source");
System.out.println("完毕!");
}
}