Add a way to compare claimed CRC (in header) of PE files with the actual CRC.

This commit is contained in:
Aneesh Dogra 2016-03-10 07:09:55 +05:30 committed by pancake
parent 977aeb8173
commit 5c3f5904ea
4 changed files with 74 additions and 0 deletions

View File

@ -558,6 +558,61 @@ struct symrec {
return true;
}
int PE_(bin_pe_get_claimed_checksum)(struct PE_(r_bin_pe_obj_t) *bin) {
return bin->nt_headers->optional_header.CheckSum;
}
int PE_(bin_pe_get_actual_checksum)(struct PE_(r_bin_pe_obj_t) *bin) {
int i, j;
int checksum_offset = bin->nt_header_offset + 4 + sizeof(PE_(image_file_header)) + 0x40;
ut8 *buf = bin->b->buf;
ut64 computed_cs = 0;
int remaining_bytes;
int shift;
ut32 cur;
for (i = 0; i < bin->size / 4; i++) {
cur = (buf[i * 4] << 0) |
(buf[i * 4 + 1] << 8) |
(buf[i * 4 + 2] << 16) |
(buf[i * 4 + 3] << 24);
// skip the checksum bytes
if (i * 4 == checksum_offset) {
continue;
}
computed_cs = (computed_cs & 0xFFFFFFFF) + cur + (computed_cs >> 32);
if (computed_cs >> 32) {
computed_cs = (computed_cs & 0xFFFFFFFF) + (computed_cs >> 32);
}
}
// add resultant bytes to checksum
remaining_bytes = bin->size % 4;
i = i * 4;
if (remaining_bytes != 0) {
cur = buf[i];
shift = 8;
for (j = 1; j < remaining_bytes; j++, shift += 8) {
cur |= buf[i + j] << shift;
}
computed_cs = (computed_cs & 0xFFFFFFFF) + cur + (computed_cs >> 32);
if (computed_cs >> 32) {
computed_cs = (computed_cs & 0xFFFFFFFF) + (computed_cs >> 32);
}
}
// 32bits -> 16bits
computed_cs = (computed_cs & 0xFFFF) + (computed_cs >> 16);
computed_cs = (computed_cs) + (computed_cs >> 16);
computed_cs = (computed_cs & 0xFFFF);
// add filesize
computed_cs += bin->size;
return computed_cs;
}
static int bin_pe_init_imports(struct PE_(r_bin_pe_obj_t) *bin) {
PE_(image_data_directory) *data_dir_import = \
&bin->nt_headers->optional_header.DataDirectory[ \

View File

@ -357,6 +357,8 @@ static int haschr(const RBinFile* arch, ut16 dllCharacteristic) {
static RBinInfo* info(RBinFile *arch) {
SDebugInfo di = {{0}};
RBinInfo *ret = R_NEW0 (RBinInfo);
ut32 claimed_checksum, actual_checksum;
if (!ret) return NULL;
arch->file = strdup (arch->file);
ret->bclass = PE_(r_bin_pe_get_class) (arch->o->bin_obj);
@ -374,12 +376,18 @@ static RBinInfo* info(RBinFile *arch) {
if (PE_(r_bin_pe_is_dll) (arch->o->bin_obj))
ret->type = strdup ("DLL (Dynamic Link Library)");
else ret->type = strdup ("EXEC (Executable file)");
claimed_checksum = PE_(bin_pe_get_claimed_checksum) (arch->o->bin_obj);
actual_checksum = PE_(bin_pe_get_actual_checksum) (arch->o->bin_obj);
ret->bits = PE_(r_bin_pe_get_bits) (arch->o->bin_obj);
ret->big_endian = PE_(r_bin_pe_is_big_endian) (arch->o->bin_obj);
ret->dbg_info = 0;
ret->has_canary = has_canary (arch);
ret->has_nx = haschr (arch, IMAGE_DLL_CHARACTERISTICS_NX_COMPAT);
ret->has_pi = haschr (arch, IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE);
ret->claimed_checksum = strdup (sdb_fmt (0, "0x%08x", claimed_checksum));
ret->actual_checksum = strdup (sdb_fmt (1, "0x%08x", actual_checksum));
sdb_bool_set (arch->sdb, "pe.canary", has_canary(arch), 0);
sdb_bool_set (arch->sdb, "pe.highva", haschr(arch, IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA), 0);
@ -394,8 +402,11 @@ static RBinInfo* info(RBinFile *arch) {
sdb_bool_set (arch->sdb, "pe.guardcf", haschr(arch, IMAGE_DLLCHARACTERISTICS_GUARD_CF), 0);
sdb_bool_set (arch->sdb, "pe.terminalserveraware", haschr(arch, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE), 0);
sdb_num_set (arch->sdb, "pe.bits", ret->bits, 0);
sdb_set (arch->sdb, "pe.claimed_checksum", ret->claimed_checksum, 0);
sdb_set (arch->sdb, "pe.actual_checksum", ret->actual_checksum, 0);
ret->has_va = true;
if (!PE_(r_bin_pe_is_stripped_debug) (arch->o->bin_obj))
ret->dbg_info |= R_BIN_DBG_STRIPPED;
if (PE_(r_bin_pe_is_stripped_line_nums) (arch->o->bin_obj))

View File

@ -507,6 +507,12 @@ static int bin_info(RCore *r, int mode) {
pair_str ("guid", info->guid, mode, false);
pair_str ("dbg_file", info->debug_file_name, mode, true);
// checksums are only supported for pe atm
if (strncmp ("pe", info->rclass, 2) == 0) {
pair_str ("crc32", info->claimed_checksum, mode, false);
pair_str ("crc32c", info->actual_checksum, mode, false);
}
for (i = 0; info->sum[i].type; i++) {
int len;

View File

@ -111,6 +111,8 @@ typedef struct r_bin_info_t {
int has_crypto;
int has_nx;
int big_endian;
char *actual_checksum;
char *claimed_checksum;
ut64 dbg_info;
RBinHash sum[3];
ut64 baddr;