“邹小朋爱邹琪”Word文档病毒修复

朋友U盘感染了病毒,文档都被杀毒软件kill了。数据恢复后打开都是乱码,让我帮忙看下。
于是对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
修复就很简单了,将损坏的文件头改回去就行了。
写了个批量修复的工具,源码如下:
[java]
public class Repair {
//遍历、检测目标目录
void detect(String path) {
File broken = new File(path);
String[] files = null; // 损坏的文件名列表

if (broken.isDirectory()) {
files = broken.list();
for (String file : files) {
detect(path + File.separator + file);
}
} else {
if ("doc".equals(path.substring(path.length() – 3, path.length())))
{
try {
startRepair(broken);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
}
//对比特征文件头检测文件是否损坏
void startRepair(File single) throws FileNotFoundException {
int[] head = new int[3]; // 特征文件头
String headString = ""; // 特征文件头

DataInputStream is = new DataInputStream(new FileInputStream(single));

try {
for (int i : head) {
i = is.readInt();
headString += Integer.toHexString(i);
}
} catch (IOException e) {
System.out.println(single + " is doubt");
e.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//匹配特征字符串
if (headString.equals("d7ded0a1c5f3b0aed7dee7f7")) {
System.out.println(single + " is broken");
modify(single);
} else {
System.out.println(single + " is ok");
}
}
//使用正常的文件头修复损坏的文件
void modify(File file) {
try {
File tempFile = new File(file.getAbsolutePath() + "(修复后).doc");

InputStream is = new BufferedInputStream(new FileInputStream(file));
OutputStream os = new BufferedOutputStream(new FileOutputStream(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 = new byte[1024];
int len = 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 (IOException e) {
e.printStackTrace();
}
System.out.println(file + " already repaired!");
}
public static void main(String[] args) {

Repair r = new Repair();
//检测c:/source下的所有文件
r.detect("c:/source");
System.out.println("完毕!");
}
}
[/java]

Join the Conversation

2 Comments

Leave a comment

Your email address will not be published. Required fields are marked *