1 /*
2 
3     File: file_mig.c
4 
5     Copyright (C) 2012 Christophe GRENIER <grenier@cgsecurity.org>
6 
7     This software is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, write the Free Software Foundation, Inc., 51
19     Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21  */
22 
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 #ifdef HAVE_STRING_H
27 #include <string.h>
28 #endif
29 #include <stdio.h>
30 #include "types.h"
31 #include "filegen.h"
32 #include "common.h"
33 #ifdef DEBUG_MIG
34 #include "log.h"
35 #endif
36 
37 static void register_header_check_mig(file_stat_t *file_stat);
38 
39 const file_hint_t file_hint_mig= {
40   .extension="mig",
41   .description="Windows Migration Backup",
42   .max_filesize=PHOTOREC_MAX_FILE_SIZE,
43   .recover=1,
44   .enable_by_default=1,
45   .register_header_check=&register_header_check_mig
46 };
47 
48 struct MIG_HDR
49 {
50   uint32_t magic;
51   uint32_t fn_size;
52   uint32_t s_size;
53   uint32_t unk1;
54   uint32_t unk2;
55   uint32_t unk3;
56   unsigned char fn[0];
57 } __attribute__ ((gcc_struct, __packed__));
58 
file_check_mig(file_recovery_t * file_recovery)59 static void file_check_mig(file_recovery_t *file_recovery)
60 {
61   struct MIG_HDR h;
62   uint64_t offset=0x34;
63   file_recovery->file_size=0;
64   while(1)
65   {
66     size_t res;
67     if(my_fseek(file_recovery->handle, offset, SEEK_SET) < 0)
68     {
69 #ifdef DEBUG_MIG
70       log_info("0x%lx fseek failed\n", (long unsigned)offset);
71 #endif
72       return ;
73     }
74     res=fread(&h, 1, sizeof(h), file_recovery->handle);
75     if(res < 8)
76     {
77 #ifdef DEBUG_MIG
78       log_info("0x%lx not enough data\n", (long unsigned)offset);
79 #endif
80       return ;
81     }
82     if(res < sizeof(h) || le32(h.magic)!=0x5354524d)	/* STRM=stream */
83     {
84 #ifdef DEBUG_MIG
85       log_info("0x%lx no magic %x\n", (long unsigned)offset, le32(h.magic));
86 #endif
87       file_recovery->file_size=offset+8;
88       return ;
89     }
90 #ifdef DEBUG_MIG
91     log_info("0x%lx magic s_size=0x%u\n", (long unsigned)offset, le32(h.s_size));
92 #endif
93     offset+=sizeof(h)+le32(h.s_size);
94   }
95 }
96 
header_check_mig(const unsigned char * buffer,const unsigned int buffer_size,const unsigned int safe_header_only,const file_recovery_t * file_recovery,file_recovery_t * file_recovery_new)97 static int header_check_mig(const unsigned char *buffer, const unsigned int buffer_size, const unsigned int safe_header_only, const file_recovery_t *file_recovery, file_recovery_t *file_recovery_new)
98 {
99   if(memcmp(&buffer[0x34], "MRTS", 4)!=0)
100     return 0;
101   reset_file_recovery(file_recovery_new);
102   file_recovery_new->extension=file_hint_mig.extension;
103   file_recovery_new->file_check=&file_check_mig;
104   return 1;
105 }
106 
register_header_check_mig(file_stat_t * file_stat)107 static void register_header_check_mig(file_stat_t *file_stat)
108 {
109   static const unsigned char mig_header[8]=  {
110     '1' , 'g' , 'i' , 'M' , 0x02, 0x00, 0x00, 0x00
111   };
112   register_header_check(0, mig_header, sizeof(mig_header), &header_check_mig, file_stat);
113 }
114