2007年8月13日 星期一

毀壞 Partition 之 Office 2003 Word 救援

身為一名軟體工程師,常常會被親戚朋友問一堆怪怪的電腦問題。
昨天就收到了兩個壞掉的隨身碟。一個 512 MB 另一個 1G 。
它們的 MBR 和 superblock 都被病毒給毀了

可是裏面的 Doc 檔又特別重要… ~_~

身為一個好人,為了未來的幸福…當然義不容辭一定要把它們救回來嘍


以下是我的救援 steps
1. 把 flash 插入可愛的 Linux 機器中。
"dmesg" check 一下是否硬體壞掉。
硬體 OK 但沒有 partition info
2. 用 "fdisk /dev/sda" check MBR
ok 真的爛了 @_@
3. 用 dd if=/dev/sda of=honey_512M.img 備份下來

4. check 資料是否完全爛掉,還好,data 還在

因為苦主說明 word 檔很重要~~ 所以就專攻 word 檔嘍
苦主用的是 office 2003,因此小弟就找了幾個 office 2003 的 word check 了一下檔頭檔尾

Good Luck!!
發現大多數的 word 檔檔頭是以 D0 CF 11 E0 A1 B1 1A E1 開頭
以 6F 63 75 6D 65 6E 74 2E 38 00 F4 39 B2 71 結尾
因此先用 hexdump + head + tail 剪一個出來驗證
驗證 OK !!

5. 隨手寫一支小小的程式把這個區段的 word 檔給一個個 copy 出來
雖然不是所有資料都救回來了,但最重要的救回來了就好了 ^_^

6. ./recover honey_512M.img

這個方法可以 recover 回文字量少(小檔案),沒有使用 macro 的doc 檔
如果檔案較大,大於 block size 那就比較麻煩了,就要去讀file system 的資料
幸運的是,絕大多數的檔案都是小檔案。
如果檔案中有圖片,就很可能變成圖片壞了,文字還是救得回來。

以下是小程式的 source Code:

Filename: recover.c
Composer: Tick
License: GPL

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const int PREFIX[] = {0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1};
const int SURFIX[] = {0x6F, 0x63, 0x75, 0x6D, 0x65, 0x6E, 0x74, 0x2E, 0x38, 0x00, 0xF4, 0x39, 0xB2, 0x71};

void showExit (char *arg) {
printf("This program is used to recover MS office files from broken image\n");
printf("Usage: %s <image file>\n",arg);
}

void recordFile(FILE *foo,char *file,int start,int end) {
FILE *fp=NULL;
if (!foo || !file || strlen(file)==0) {
printf("Invalid file to record (%d,%d)\n",start,end);
return;
}
fp = fopen(file,"w");
if (fp == NULL) {
printf("open record file %s failed!!\n",file);
return;
}
fseek(foo,start,SEEK_SET);
while (ftell(foo) < end) {
fputc(fgetc(foo),fp);
}
fclose(fp);
}


void scanFile(FILE * foo) {
int c;
int index=0,index_e=0;
int start=0,end=0;
int fid=1;
char buf[256];
while (!feof(foo)) {
c = fgetc(foo);
// printf("get 0x%02x at %d PREFIX[%d]=0x%02x\n", c, (int)ftell(foo),index,PREFIX[index]);
if (c==PREFIX[index]) {
index++;
}else {
index=0;
}
if(index==(sizeof(PREFIX)/sizeof(PREFIX[0]))) {
printf("Get PREFIX at %d index = %d\n",(int)ftell(foo)-index, index);
start=(int)ftell(foo)-index;
index=0;
}

if (start!=0) {
if (c==SURFIX[index_e]) {
index_e++;
}else {
index_e=0;
}
if (index_e==(sizeof(SURFIX)/sizeof(SURFIX[0]))) {
end=(int)ftell(foo);
printf(" File starts at %d end at %d size %d bytes\n",start,end,end-start);
sprintf(buf,"%04d.doc",fid++);
recordFile(foo,buf,start,end);
start=0;
index_e=0;
}
}
}
}

int main (int args,char **argv) {
FILE *foo;
if(args == 1 ) {
showExit(argv[0]);
return 0;
}
foo = fopen(argv[1],"r");
if (!foo) {
printf("Open File %s failed!!\n",argv[1]);
return 0;
}
printf("Open File OK!!\n");

scanFile(foo);

fclose(foo);
}

1 則留言:

Kuolong 提到...

好小子, 竟然躲在這裡.
哈~~~以後硬碟壞掉知道要找誰了 :-)

庫龍