summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2013-03-23 14:58:31 +0100
committerChristophe Grenier <grenier@cgsecurity.org>2013-03-23 14:58:31 +0100
commite049dc130dab9c34dcfb58d98efb601e7f231814 (patch)
tree4bad66a08c3320f2b1ed334da40411998b9601af
parent0fde565a7457498ac38df5cc2a7d6fa41c4d8ca0 (diff)
PhotoRec: stricter check for .reg detection
-rw-r--r--src/file_reg.c85
1 files changed, 70 insertions, 15 deletions
diff --git a/src/file_reg.c b/src/file_reg.c
index cf733e8..b16138d 100644
--- a/src/file_reg.c
+++ b/src/file_reg.c
@@ -45,28 +45,83 @@ const file_hint_t file_hint_reg= {
.register_header_check=&register_header_check_reg
};
-static const unsigned char reg_header_nt[4] = { 'r','e','g','f'};
-static const unsigned char reg_header_9x[4] = { 'C','R','E','G'};
+struct creg_file_header
+{
+ uint32_t CREG_ID; /* CREG */
+ uint32_t uk1;
+ uint32_t rgdb_offset;
+ uint32_t chksum;
+ uint16_t num_rgdb;
+ uint16_t flags;
+ uint32_t uk2;
+ uint32_t uk3;
+ uint32_t uk4;
+} __attribute__ ((__packed__));
-static void register_header_check_reg(file_stat_t *file_stat)
+typedef struct rgdb_block
{
- register_header_check(0, reg_header_nt,sizeof(reg_header_nt), &header_check_reg, file_stat);
- register_header_check(0, reg_header_9x,sizeof(reg_header_9x), &header_check_reg, file_stat);
+ uint32_t RGDB_ID; /* RGDB */
+ uint32_t size;
+ uint32_t unused_size;
+ uint16_t flags;
+ uint16_t section;
+ uint32_t free_offset; /* -1 if there is no free space */
+ uint16_t max_id;
+ uint16_t first_free_id;
+ uint32_t uk1;
+ uint32_t chksum;
+} __attribute__ ((__packed__));
+
+static int header_check_reg_9x(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)
+{
+ const struct creg_file_header*header=(const struct creg_file_header*)buffer;
+ const struct rgdb_block*block=(const struct rgdb_block*)buffer+le32(header->rgdb_offset);
+ if(le32(header->rgdb_offset)+4 > buffer_size)
+ return 0;
+ if(memcmp(block,"RGDB",4)!=0)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->min_filesize=0x1000;
+ file_recovery_new->extension=file_hint_reg.extension;
+ return 1;
}
-static int header_check_reg(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)
+struct regf_file_header
{
- if(memcmp(buffer,reg_header_9x,sizeof(reg_header_9x))==0 ||
- memcmp(buffer,reg_header_nt,sizeof(reg_header_nt))==0)
- {
- reset_file_recovery(file_recovery_new);
- file_recovery_new->min_filesize=0x1000,
- file_recovery_new->extension=file_hint_reg.extension;
- return 1;
- }
- return 0;
+ uint32_t signature;
+ uint32_t primary_sequence_number;
+ uint32_t secondary_sequence_number;
+ uint64_t modification_time;
+ uint32_t major_version;
+ uint32_t minor_version;
+ uint32_t file_type;
+ uint32_t unknown3;
+ uint32_t root_key_offset;
+ uint32_t hive_bins_size;
+ uint32_t unknown4;
+ uint8_t unknown5[ 64 ];
+ uint8_t unknown6[ 396 ];
+ uint32_t xor_checksum;
+} __attribute__ ((__packed__));
+
+static int header_check_reg_nt(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)
+{
+ const struct regf_file_header *header=(const struct regf_file_header*)buffer;
+ if(le32(header->file_type) > 1)
+ return 0;
+ reset_file_recovery(file_recovery_new);
+ file_recovery_new->min_filesize=0x1000;
+ file_recovery_new->extension=file_hint_reg.extension;
+ return 1;
}
/* TODO: use information from http://home.eunet.no/pnordahl/ntpasswd/WinReg.txt to get the file size
Registry: regf hbin hbin...
*/
+static void register_header_check_reg(file_stat_t *file_stat)
+{
+ static const unsigned char reg_header_nt[4] = { 'r','e','g','f'};
+ static const unsigned char reg_header_9x[4] = { 'C','R','E','G'};
+ register_header_check(0, reg_header_nt,sizeof(reg_header_nt), &header_check_reg_nt, file_stat);
+ register_header_check(0, reg_header_9x,sizeof(reg_header_9x), &header_check_reg_9x, file_stat);
+}