Commit message: Fix crash in pe
CVE: CVE-2018-11379
CWE: CWE-125
Vulnerability description: The get_debug_info() function in radare2 2.5.0 allows remote attackers to cause a denial of service (heap-based out-of-bounds read and application crash) via a crafted PE file.

Project: radare2
File: pe.c

struct PE_(r_bin_pe_obj_t)* PE_(r_bin_pe_new)(const char* file, bool verbose) {
	ut8* buf;
	struct PE_(r_bin_pe_obj_t)* bin = R_NEW0 (struct PE_(r_bin_pe_obj_t));
	if (!bin) {
		return NULL;
	}
	bin->file = file;
	if (!(buf = (ut8*) r_file_slurp (file, &bin->size))) {
		return PE_(r_bin_pe_free)(bin);
	}
	bin->b = r_buf_new ();
	if (!r_buf_set_bytes (bin->b, buf, bin->size)) {
		free (buf);
		return PE_(r_bin_pe_free)(bin);
	}
	bin->verbose = verbose;
	free (buf);
	if (!bin_pe_init (bin)) {
		return PE_(r_bin_pe_free)(bin);
	}
	return bin;
}

Project: radare2
File: pe.c

struct PE_(r_bin_pe_obj_t)* PE_(r_bin_pe_new_buf)(RBuffer * buf, bool verbose) {
	struct PE_(r_bin_pe_obj_t)* bin = R_NEW0 (struct PE_(r_bin_pe_obj_t));
	if (!bin) {
		return NULL;
	}
	bin->kv = sdb_new0 ();
	bin->b = r_buf_new ();
	bin->verbose = verbose;
	bin->size = buf->length;
	if (!r_buf_set_bytes (bin->b, buf->buf, bin->size)) {
		return PE_(r_bin_pe_free)(bin);
	}
	if (!bin_pe_init (bin)) {
		return PE_(r_bin_pe_free)(bin);
	}
	return bin;
}

Project: radare2
File: pe.c

static String* Pe_r_bin_pe_parse_string(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord* curAddr) {
	String* string = calloc (1, sizeof(*string));
	PE_DWord begAddr = *curAddr;
	int len_value = 0;
	int i = 0;
	if (!string) {
		bprintf ("Warning: calloc (String)\n");
		return NULL;
	}
	if (begAddr > bin->size || begAddr + sizeof(string->wLength) > bin->size) {
		free_String (string);
		return NULL;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &string->wLength, sizeof(string->wLength)) != sizeof(string->wLength)) {
		bprintf ("Warning: read (String wLength)\n");
		goto out_error;
	}
	*curAddr += sizeof(string->wLength);
	if (*curAddr > bin->size || *curAddr + sizeof(string->wValueLength) > bin->size) {
		goto out_error;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &string->wValueLength, sizeof(string->wValueLength)) != sizeof(string->wValueLength)) {
		bprintf ("Warning: read (String wValueLength)\n");
		goto out_error;
	}
	*curAddr += sizeof(string->wValueLength);

	if (*curAddr > bin->size || *curAddr + sizeof(string->wType) > bin->size) {
		goto out_error;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &string->wType, sizeof(string->wType)) != sizeof(string->wType)) {
		bprintf ("Warning: read (String wType)\n");
		goto out_error;
	}
	*curAddr += sizeof(string->wType);
	if (string->wType != 0 && string->wType != 1) {
		bprintf ("Warning: check (String wType)\n");
		goto out_error;
	}

	for (i = 0; *curAddr < begAddr + string->wLength; ++i, *curAddr += sizeof (ut16)) {
		ut16 utf16_char;
		if (*curAddr > bin->size || *curAddr + sizeof (ut16) > bin->size) {
			goto out_error;
		}
		if (r_buf_read_at (bin->b, *curAddr, (ut8*) &utf16_char, sizeof (ut16)) != sizeof (ut16)) {
			bprintf ("Warning: check (String szKey)\n");
			goto out_error;
		}
		string->szKey = (ut16*) realloc (string->szKey, (i + 1) * sizeof (ut16));
		string->szKey[i] = utf16_char;
		string->wKeyLen += sizeof (ut16);
		if (!utf16_char) {
			*curAddr += sizeof (ut16);
			break;
		}
	}
	align32 (*curAddr);
	len_value = R_MIN (string->wValueLength * 2, string->wLength - (*curAddr - begAddr));
	string->wValueLength = len_value;
	if (len_value < 0) {
		len_value = 0;
	}
	string->Value = (ut16*) calloc (len_value + 1, 1);
	if (!string->Value) {
		bprintf ("Warning: malloc (String Value)\n");
		goto out_error;
	}
	if (*curAddr > bin->size || *curAddr + len_value > bin->size) {
		goto out_error;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) string->Value, len_value) != len_value) {
		bprintf ("Warning: read (String Value)\n");
		goto out_error;
	}
	*curAddr += len_value;
	return string;
out_error:
	free_String (string);
	return NULL;
}

Project: radare2
File: pe.c

static StringFileInfo* Pe_r_bin_pe_parse_string_file_info(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord* curAddr) {
	StringFileInfo* stringFileInfo = calloc (1, sizeof(*stringFileInfo));
	if (!stringFileInfo) {
		bprintf ("Warning: calloc (StringFileInfo)\n");
		return NULL;
	}

	PE_DWord startAddr = *curAddr;

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringFileInfo->wLength, sizeof(stringFileInfo->wLength)) != sizeof(stringFileInfo->wLength)) {
		bprintf ("Warning: read (StringFileInfo wLength)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}
	*curAddr += sizeof(stringFileInfo->wLength);

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringFileInfo->wValueLength, sizeof(stringFileInfo->wValueLength)) != sizeof(stringFileInfo->wValueLength)) {
		bprintf ("Warning: read (StringFileInfo wValueLength)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}
	*curAddr += sizeof(stringFileInfo->wValueLength);

	if (stringFileInfo->wValueLength) {
		bprintf ("Warning: check (StringFileInfo wValueLength)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringFileInfo->wType, sizeof(stringFileInfo->wType)) != sizeof(stringFileInfo->wType)) {
		bprintf ("Warning: read (StringFileInfo wType)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}
	*curAddr += sizeof(stringFileInfo->wType);

	if (stringFileInfo->wType && stringFileInfo->wType != 1) {
		bprintf ("Warning: check (StringFileInfo wType)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}

	stringFileInfo->szKey = (ut16*) malloc (UT16_ALIGN (STRINGFILEINFO_UTF_16_LEN));  //L"StringFileInfo"
	if (!stringFileInfo->szKey) {
		bprintf ("Warning: malloc (StringFileInfo szKey)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) stringFileInfo->szKey, STRINGFILEINFO_UTF_16_LEN) != STRINGFILEINFO_UTF_16_LEN) {
		bprintf ("Warning: read (StringFileInfo szKey)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}
	*curAddr += STRINGFILEINFO_UTF_16_LEN;

	if (memcmp (stringFileInfo->szKey, STRINGFILEINFO_UTF_16, STRINGFILEINFO_UTF_16_LEN) != 0) {
		bprintf ("Warning: check (StringFileInfo szKey)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}

	align32 (*curAddr);

	while (startAddr + stringFileInfo->wLength > *curAddr) {
		StringTable** tmp = (StringTable**) realloc (stringFileInfo->Children, (stringFileInfo->numOfChildren + 1) * sizeof(*stringFileInfo->Children));
		if (!tmp) {
			bprintf ("Warning: realloc (StringFileInfo Children)\n");
			free_StringFileInfo (stringFileInfo);
			return NULL;
		}
		stringFileInfo->Children = tmp;
		if (!(stringFileInfo->Children[stringFileInfo->numOfChildren] = Pe_r_bin_pe_parse_string_table (bin, curAddr))) {
			bprintf ("Warning: bad parsing StringTable\n");
			free_StringFileInfo (stringFileInfo);
			return NULL;
		}
		stringFileInfo->numOfChildren++;
		align32 (*curAddr);
	}

	if (!stringFileInfo->numOfChildren) {
		bprintf ("Warning: check (StringFileInfo numOfChildren)\n");
		free_StringFileInfo (stringFileInfo);
		return NULL;
	}

	return stringFileInfo;
}

Project: radare2
File: pe.c

static StringTable* Pe_r_bin_pe_parse_string_table(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord* curAddr) {
	StringTable* stringTable = calloc (1, sizeof(*stringTable));
	if (!stringTable) {
		bprintf ("Warning: calloc (stringTable)\n");
		return NULL;
	}

	PE_DWord startAddr = *curAddr;
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringTable->wLength, sizeof(stringTable->wLength)) != sizeof(stringTable->wLength)) {
		bprintf ("Warning: read (StringTable wLength)\n");
		free_StringTable (stringTable);
		return NULL;
	}
	*curAddr += sizeof(stringTable->wLength);

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringTable->wValueLength, sizeof(stringTable->wValueLength)) != sizeof(stringTable->wValueLength)) {
		bprintf ("Warning: read (StringTable wValueLength)\n");
		free_StringTable (stringTable);
		return NULL;
	}
	*curAddr += sizeof(stringTable->wValueLength);

	if (stringTable->wValueLength) {
		bprintf ("Warning: check (StringTable wValueLength)\n");
		free_StringTable (stringTable);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &stringTable->wType, sizeof(stringTable->wType)) != sizeof(stringTable->wType)) {
		bprintf ("Warning: read (StringTable wType)\n");
		free_StringTable (stringTable);
		return NULL;
	}
	*curAddr += sizeof(stringTable->wType);
	if (stringTable->wType && stringTable->wType != 1) {
		bprintf ("Warning: check (StringTable wType)\n");
		free_StringTable (stringTable);
		return NULL;
	}
	stringTable->szKey = (ut16*) malloc (UT16_ALIGN (EIGHT_HEX_DIG_UTF_16_LEN));  //EIGHT_HEX_DIG_UTF_16_LEN
	if (!stringTable->szKey) {
		bprintf ("Warning: malloc (stringTable szKey)\n");
		free_StringTable (stringTable);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) stringTable->szKey, EIGHT_HEX_DIG_UTF_16_LEN) != EIGHT_HEX_DIG_UTF_16_LEN) {
		bprintf ("Warning: read (StringTable szKey)\n");
		free_StringTable (stringTable);
		return NULL;
	}
	*curAddr += EIGHT_HEX_DIG_UTF_16_LEN;
	align32 (*curAddr);
	while (startAddr + stringTable->wLength > *curAddr) {
		String** tmp = (String**) realloc (stringTable->Children, (stringTable->numOfChildren + 1) * sizeof(*stringTable->Children));
		if (!tmp) {
			bprintf ("Warning: realloc (StringTable Children)\n");
			free_StringTable (stringTable);
			return NULL;
		}
		stringTable->Children = tmp;
		if (!(stringTable->Children[stringTable->numOfChildren] = Pe_r_bin_pe_parse_string (bin, curAddr))) {
			bprintf ("Warning: bad parsing String\n");
			free_StringTable (stringTable);
			return NULL;
		}
		stringTable->numOfChildren++;
		align32 (*curAddr);
	}

	if (!stringTable->numOfChildren) {
		bprintf ("Warning: check (StringTable numOfChildren)\n");
		free_StringTable (stringTable);
		return NULL;
	}

	return stringTable;
}

Project: radare2
File: pe.c

static Var* Pe_r_bin_pe_parse_var(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord* curAddr) {
	Var* var = calloc (1, sizeof(*var));
	if (!var) {
		bprintf ("Warning: calloc (Var)\n");
		return NULL;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &var->wLength, sizeof(var->wLength)) != sizeof(var->wLength)) {
		bprintf ("Warning: read (Var wLength)\n");
		free_Var (var);
		return NULL;
	}
	*curAddr += sizeof(var->wLength);
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &var->wValueLength, sizeof(var->wValueLength)) != sizeof(var->wValueLength)) {
		bprintf ("Warning: read (Var wValueLength)\n");
		free_Var (var);
		return NULL;
	}
	*curAddr += sizeof(var->wValueLength);
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &var->wType, sizeof(var->wType)) != sizeof(var->wType)) {
		bprintf ("Warning: read (Var wType)\n");
		free_Var (var);
		return NULL;
	}
	*curAddr += sizeof(var->wType);
	if (var->wType != 0 && var->wType != 1) {
		bprintf ("Warning: check (Var wType)\n");
		free_Var (var);
		return NULL;
	}

	var->szKey = (ut16*) malloc (UT16_ALIGN (TRANSLATION_UTF_16_LEN));  //L"Translation"
	if (!var->szKey) {
		bprintf ("Warning: malloc (Var szKey)\n");
		free_Var (var);
		return NULL;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) var->szKey, TRANSLATION_UTF_16_LEN) < 1) {
		bprintf ("Warning: read (Var szKey)\n");
		free_Var (var);
		return NULL;
	}
	*curAddr += TRANSLATION_UTF_16_LEN;
	if (memcmp (var->szKey, TRANSLATION_UTF_16, TRANSLATION_UTF_16_LEN)) {
		bprintf ("Warning: check (Var szKey)\n");
		free_Var (var);
		return NULL;
	}
	align32 (*curAddr);
	var->numOfValues = var->wValueLength / 4;
	if (!var->numOfValues) {
		bprintf ("Warning: check (Var numOfValues)\n");
		free_Var (var);
		return NULL;
	}
	var->Value = (ut32*) malloc (var->wValueLength);
	if (!var->Value) {
		bprintf ("Warning: malloc (Var Value)\n");
		free_Var (var);
		return NULL;
	}
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) var->Value, var->wValueLength) != var->wValueLength) {
		bprintf ("Warning: read (Var Value)\n");
		free_Var (var);
		return NULL;
	}
	*curAddr += var->wValueLength;
	return var;
}

Project: radare2
File: pe.c

static VarFileInfo* Pe_r_bin_pe_parse_var_file_info(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord* curAddr) {
	VarFileInfo* varFileInfo = calloc (1, sizeof(*varFileInfo));
	if (!varFileInfo) {
		bprintf ("Warning: calloc (VarFileInfo)\n");
		return NULL;
	}
	PE_DWord startAddr = *curAddr;
	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &varFileInfo->wLength, sizeof(varFileInfo->wLength)) != sizeof(varFileInfo->wLength)) {
		bprintf ("Warning: read (VarFileInfo wLength)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}
	*curAddr += sizeof(varFileInfo->wLength);

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &varFileInfo->wValueLength, sizeof(varFileInfo->wValueLength)) != sizeof(varFileInfo->wValueLength)) {
		bprintf ("Warning: read (VarFileInfo wValueLength)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}
	*curAddr += sizeof(varFileInfo->wValueLength);

	if (varFileInfo->wValueLength != 0) {
		bprintf ("Warning: check (VarFileInfo wValueLength)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) &varFileInfo->wType, sizeof(varFileInfo->wType)) != sizeof(varFileInfo->wType)) {
		bprintf ("Warning: read (VarFileInfo wType)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}
	*curAddr += sizeof(varFileInfo->wType);
	if (varFileInfo->wType && varFileInfo->wType != 1) {
		bprintf ("Warning: check (VarFileInfo wType)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}

	varFileInfo->szKey = (ut16*) malloc (UT16_ALIGN (VARFILEINFO_UTF_16_LEN ));  //L"VarFileInfo"
	if (!varFileInfo->szKey) {
		bprintf ("Warning: malloc (VarFileInfo szKey)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}

	if (r_buf_read_at (bin->b, *curAddr, (ut8*) varFileInfo->szKey, VARFILEINFO_UTF_16_LEN) != VARFILEINFO_UTF_16_LEN) {
		bprintf ("Warning: read (VarFileInfo szKey)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}
	*curAddr += VARFILEINFO_UTF_16_LEN;

	if (memcmp (varFileInfo->szKey, VARFILEINFO_UTF_16, VARFILEINFO_UTF_16_LEN)) {
		bprintf ("Warning: check (VarFileInfo szKey)\n");
		free_VarFileInfo (varFileInfo);
		return NULL;
	}
	align32 (*curAddr);
	while (startAddr + varFileInfo->wLength > *curAddr) {
		Var** tmp = (Var**) realloc (varFileInfo->Children, (varFileInfo->numOfChildren + 1) * sizeof(*varFileInfo->Children));
		if (!tmp) {
			bprintf ("Warning: realloc (VarFileInfo Children)\n");
			free_VarFileInfo (varFileInfo);
			return NULL;
		}
		varFileInfo->Children = tmp;
		if (!(varFileInfo->Children[varFileInfo->numOfChildren] = Pe_r_bin_pe_parse_var (bin, curAddr))) {
			bprintf ("Warning: bad parsing Var\n");
			free_VarFileInfo (varFileInfo);
			return NULL;
		}
		varFileInfo->numOfChildren++;
		align32 (*curAddr);
	}
	return varFileInfo;
}

Project: radare2

static PE_VS_VERSIONINFO* Pe_r_bin_pe_parse_version_info(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord version_info_paddr) {
	ut32 sz;
	PE_VS_VERSIONINFO* vs_VersionInfo = calloc (1, sizeof(PE_VS_VERSIONINFO));
	if (!vs_VersionInfo) {
		return NULL;
	}
	PE_DWord startAddr = version_info_paddr;
	PE_DWord curAddr = version_info_paddr;
	sz = sizeof(ut16);
	EXIT_ON_OVERFLOW (sz);
	if (r_buf_read_at (bin->b, curAddr, (ut8*) &vs_VersionInfo->wLength, sz) != sz) {
		bprintf ("Warning: read (VS_VERSIONINFO wLength)\n");
		goto out_error;
	}
	curAddr += sz;
	EXIT_ON_OVERFLOW (sz);
	if (r_buf_read_at (bin->b, curAddr, (ut8*) &vs_VersionInfo->wValueLength, sz) != sz) {
		bprintf ("Warning: read (VS_VERSIONINFO wValueLength)\n");
		goto out_error;
	}
	curAddr += sz;
	EXIT_ON_OVERFLOW (sz);
	if (r_buf_read_at (bin->b, curAddr, (ut8*) &vs_VersionInfo->wType, sz) != sz) {
		bprintf ("Warning: read (VS_VERSIONINFO wType)\n");
		goto out_error;
	}
	curAddr += sz;
	if (vs_VersionInfo->wType && vs_VersionInfo->wType != 1) {
		bprintf ("Warning: check (VS_VERSIONINFO wType)\n");
		goto out_error;
	}

	vs_VersionInfo->szKey = (ut16*) malloc (UT16_ALIGN (VS_VERSION_INFO_UTF_16_LEN));  //L"VS_VERSION_INFO"
	if (!vs_VersionInfo->szKey) {
		bprintf ("Warning: malloc (VS_VERSIONINFO szKey)\n");
		goto out_error;
	}
	sz = VS_VERSION_INFO_UTF_16_LEN;
	EXIT_ON_OVERFLOW (sz);
	if (r_buf_read_at (bin->b, curAddr, (ut8*) vs_VersionInfo->szKey, sz) != sz) {
		bprintf ("Warning: read (VS_VERSIONINFO szKey)\n");
		goto out_error;
	}
	curAddr += sz;
	if (memcmp (vs_VersionInfo->szKey, VS_VERSION_INFO_UTF_16, sz)) {
		goto out_error;
	}
	align32 (curAddr);
	if (vs_VersionInfo->wValueLength) {
		if (vs_VersionInfo->wValueLength != sizeof (*vs_VersionInfo->Value)) {
			bprintf ("Warning: check (VS_VERSIONINFO wValueLength != sizeof PE_VS_FIXEDFILEINFO)\n");
			goto out_error;
		}

		vs_VersionInfo->Value = (PE_VS_FIXEDFILEINFO*) malloc (sizeof(*vs_VersionInfo->Value));
		if (!vs_VersionInfo->Value) {
			bprintf ("Warning: malloc (VS_VERSIONINFO Value)\n");
			goto out_error;
		}
		sz = sizeof(PE_VS_FIXEDFILEINFO);
		EXIT_ON_OVERFLOW (sz);
		if (r_buf_read_at (bin->b, curAddr, (ut8*) vs_VersionInfo->Value, sz) != sz) {
			bprintf ("Warning: read (VS_VERSIONINFO Value)\n");
			goto out_error;
		}

		if (vs_VersionInfo->Value->dwSignature != 0xFEEF04BD) {
			bprintf ("Warning: check (PE_VS_FIXEDFILEINFO signature) 0x%08x\n", vs_VersionInfo->Value->dwSignature);
			goto out_error;
		}
		curAddr += sz;
		align32 (curAddr);
	}

	if (startAddr + vs_VersionInfo->wLength > curAddr) {
		char t = '\0';
		if (curAddr + 3 * sizeof(ut16) > bin->size || curAddr + 3 + sizeof(ut64) + 1 > bin->size) {
			goto out_error;
		}
		if (r_buf_read_at (bin->b, curAddr + 3 * sizeof(ut16), (ut8*) &t, 1) != 1) {
			bprintf ("Warning: read (VS_VERSIONINFO Children V or S)\n");
			goto out_error;
		}
		if (!(t == 'S' || t == 'V')) {
			bprintf ("Warning: bad type (VS_VERSIONINFO Children)\n");
			goto out_error;
		}
		if (t == 'S') {
			if (!(vs_VersionInfo->stringFileInfo = Pe_r_bin_pe_parse_string_file_info (bin, &curAddr))) {
				bprintf ("Warning: bad parsing (VS_VERSIONINFO StringFileInfo)\n");
				goto out_error;
			}
		}
		if (t == 'V') {
			if (!(vs_VersionInfo->varFileInfo = Pe_r_bin_pe_parse_var_file_info (bin, &curAddr))) {
				bprintf ("Warning: bad parsing (VS_VERSIONINFO VarFileInfo)\n");
				goto out_error;
			}
		}

		align32 (curAddr);

		if (startAddr + vs_VersionInfo->wLength > curAddr) {
			if (t == 'V') {
				if (!(vs_VersionInfo->stringFileInfo = Pe_r_bin_pe_parse_string_file_info (bin, &curAddr))) {
					bprintf ("Warning: bad parsing (VS_VERSIONINFO StringFileInfo)\n");
					goto out_error;
				}
			} else if (t == 'S') {
				if (!(vs_VersionInfo->varFileInfo = Pe_r_bin_pe_parse_var_file_info (bin, &curAddr))) {
					bprintf ("Warning: bad parsing (VS_VERSIONINFO VarFileInfo)\n");
					goto out_error;
				}
			}
			if (startAddr + vs_VersionInfo->wLength > curAddr) {
				bprintf ("Warning: bad parsing (VS_VERSIONINFO wLength left)\n");
				goto out_error;
			}
		}
	}
	return vs_VersionInfo;
out_error:
	free_VS_VERSIONINFO (vs_VersionInfo);
	return NULL;

}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_fixed_file_info(PE_VS_FIXEDFILEINFO* vs_fixedFileInfo) {
	Sdb* sdb = NULL;
	if (!vs_fixedFileInfo) {
		return NULL;
	}
	sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	sdb_num_set (sdb, "Signature",        vs_fixedFileInfo->dwSignature,        0);
	sdb_num_set (sdb, "StrucVersion",     vs_fixedFileInfo->dwStrucVersion,     0);
	sdb_num_set (sdb, "FileVersionMS",    vs_fixedFileInfo->dwFileVersionMS,    0);
	sdb_num_set (sdb, "FileVersionLS",    vs_fixedFileInfo->dwFileVersionLS,    0);
	sdb_num_set (sdb, "ProductVersionMS", vs_fixedFileInfo->dwProductVersionMS, 0);
	sdb_num_set (sdb, "ProductVersionLS", vs_fixedFileInfo->dwProductVersionLS, 0);
	sdb_num_set (sdb, "FileFlagsMask",    vs_fixedFileInfo->dwFileFlagsMask,    0);
	sdb_num_set (sdb, "FileFlags",        vs_fixedFileInfo->dwFileFlags,        0);
	sdb_num_set (sdb, "FileOS",           vs_fixedFileInfo->dwFileOS,           0);
	sdb_num_set (sdb, "FileType",         vs_fixedFileInfo->dwFileType,         0);
	sdb_num_set (sdb, "FileSubtype",      vs_fixedFileInfo->dwFileSubtype,      0);
	sdb_num_set (sdb, "FileDateMS",       vs_fixedFileInfo->dwFileDateMS,       0);
	sdb_num_set (sdb, "FileDateLS",       vs_fixedFileInfo->dwFileDateLS,       0);
	return sdb;
}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_resource_version_info(PE_VS_VERSIONINFO* vs_VersionInfo) {
	Sdb* sdb = NULL;
	if (!vs_VersionInfo) {
		return NULL;
	}
	sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	if (vs_VersionInfo->Value) {
		sdb_ns_set (sdb, "fixed_file_info", Pe_r_bin_store_fixed_file_info (vs_VersionInfo->Value));
	}
	if (vs_VersionInfo->varFileInfo) {
		sdb_ns_set (sdb, "var_file_info", Pe_r_bin_store_var_file_info (vs_VersionInfo->varFileInfo));
	}
	if (vs_VersionInfo->stringFileInfo) {
		sdb_ns_set (sdb, "string_file_info", Pe_r_bin_store_string_file_info (vs_VersionInfo->stringFileInfo));
	}
	return sdb;
}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_string(String* string) {
	Sdb* sdb = NULL;
	char* encodedVal = NULL, * encodedKey = NULL;
	if (!string) {
		return NULL;
	}
	sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	encodedKey = sdb_encode ((unsigned char*) string->szKey, string->wKeyLen);
	if (!encodedKey) {
		sdb_free (sdb);
		return NULL;
	}
	encodedVal = sdb_encode ((unsigned char*) string->Value, string->wValueLength);
	if (!encodedVal) {
		free (encodedKey);
		sdb_free (sdb);
		return NULL;
	}
	sdb_set (sdb, "key",   encodedKey, 0);
	sdb_set (sdb, "value", encodedVal, 0);
	free (encodedKey);
	free (encodedVal);
	return sdb;
}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_string_file_info(StringFileInfo* stringFileInfo) {
	char key[30];
	int i = 0;
	Sdb* sdb = NULL;
	if (!stringFileInfo) {
		return NULL;
	}
	sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	for (; i < stringFileInfo->numOfChildren; i++) {
		snprintf (key, 30, "stringtable%d", i);
		sdb_ns_set (sdb, key, Pe_r_bin_store_string_table (stringFileInfo->Children[i]));
	}
	return sdb;
}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_var_file_info(VarFileInfo* varFileInfo) {
	char key[20];
	unsigned int i = 0;
	if (!varFileInfo) {
		return NULL;
	}
	Sdb* sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	for (; i < varFileInfo->numOfChildren; i++) {
		snprintf (key, 20, "var%d", i);
		sdb_ns_set (sdb, key, Pe_r_bin_store_var (varFileInfo->Children[i]));
	}
	return sdb;
}

Project: radare2
File: pe.c

static void _free_resources(r_pe_resource *rs) {
	if (rs) {
		free (rs->timestr);
		free (rs->data);
		free (rs->type);
		free (rs->language);
		free (rs);
	}
}

Project: radare2
File: pe.c

static char* _resource_lang_str(int id) {
	switch(id) {
	case 0x00: return "LANG_NEUTRAL";
	case 0x7f: return "LANG_INVARIANT";
	case 0x36: return "LANG_AFRIKAANS";
	case 0x1c: return "LANG_ALBANIAN ";
	case 0x01: return "LANG_ARABIC";
	case 0x2b: return "LANG_ARMENIAN";
	case 0x4d: return "LANG_ASSAMESE";
	case 0x2c: return "LANG_AZERI";
	case 0x2d: return "LANG_BASQUE";
	case 0x23: return "LANG_BELARUSIAN";
	case 0x45: return "LANG_BENGALI";
	case 0x02: return "LANG_BULGARIAN";
	case 0x03: return "LANG_CATALAN";
	case 0x04: return "LANG_CHINESE";
	case 0x1a: return "LANG_CROATIAN";
	case 0x05: return "LANG_CZECH";
	case 0x06: return "LANG_DANISH";
	case 0x65: return "LANG_DIVEHI";
	case 0x13: return "LANG_DUTCH";
	case 0x09: return "LANG_ENGLISH";
	case 0x25: return "LANG_ESTONIAN";
	case 0x38: return "LANG_FAEROESE";
	case 0x29: return "LANG_FARSI";
	case 0x0b: return "LANG_FINNISH";
	case 0x0c: return "LANG_FRENCH";
	case 0x56: return "LANG_GALICIAN";
	case 0x37: return "LANG_GEORGIAN";
	case 0x07: return "LANG_GERMAN";
	case 0x08: return "LANG_GREEK";
	case 0x47: return "LANG_GUJARATI";
	case 0x0d: return "LANG_HEBREW";
	case 0x39: return "LANG_HINDI";
	case 0x0e: return "LANG_HUNGARIAN";
	case 0x0f: return "LANG_ICELANDIC";
	case 0x21: return "LANG_INDONESIAN";
	case 0x10: return "LANG_ITALIAN";
	case 0x11: return "LANG_JAPANESE";
	case 0x4b: return "LANG_KANNADA";
	case 0x60: return "LANG_KASHMIRI";
	case 0x3f: return "LANG_KAZAK";
	case 0x57: return "LANG_KONKANI";
	case 0x12: return "LANG_KOREAN";
	case 0x40: return "LANG_KYRGYZ";
	case 0x26: return "LANG_LATVIAN";
	case 0x27: return "LANG_LITHUANIAN";
	case 0x2f: return "LANG_MACEDONIAN";
	case 0x3e: return "LANG_MALAY";
	case 0x4c: return "LANG_MALAYALAM";
	case 0x58: return "LANG_MANIPURI";
	case 0x4e: return "LANG_MARATHI";
	case 0x50: return "LANG_MONGOLIAN";
	case 0x61: return "LANG_NEPALI";
	case 0x14: return "LANG_NORWEGIAN";
	case 0x48: return "LANG_ORIYA";
	case 0x15: return "LANG_POLISH";
	case 0x16: return "LANG_PORTUGUESE";
	case 0x46: return "LANG_PUNJABI";
	case 0x18: return "LANG_ROMANIAN";
	case 0x19: return "LANG_RUSSIAN";
	case 0x4f: return "LANG_SANSKRIT";
	case 0x59: return "LANG_SINDHI";
	case 0x1b: return "LANG_SLOVAK";
	case 0x24: return "LANG_SLOVENIAN";
	case 0x0a: return "LANG_SPANISH ";
	case 0x41: return "LANG_SWAHILI";
	case 0x1d: return "LANG_SWEDISH";
	case 0x5a: return "LANG_SYRIAC";
	case 0x49: return "LANG_TAMIL";
	case 0x44: return "LANG_TATAR";
	case 0x4a: return "LANG_TELUGU";
	case 0x1e: return "LANG_THAI";
	case 0x1f: return "LANG_TURKISH";
	case 0x22: return "LANG_UKRAINIAN";
	case 0x20: return "LANG_URDU";
	case 0x43: return "LANG_UZBEK";
	case 0x2a: return "LANG_VIETNAMESE";
	case 0x3c: return "LANG_GAELIC";
	case 0x3a: return "LANG_MALTESE";
	case 0x28: return "LANG_MAORI";
	case 0x17: return "LANG_RHAETO_ROMANCE";
	case 0x3b: return "LANG_SAAMI";
	case 0x2e: return "LANG_SORBIAN";
	case 0x30: return "LANG_SUTU";
	case 0x31: return "LANG_TSONGA";
	case 0x32: return "LANG_TSWANA";
	case 0x33: return "LANG_VENDA";
	case 0x34: return "LANG_XHOSA";
	case 0x35: return "LANG_ZULU";
	case 0x8f: return "LANG_ESPERANTO";
	case 0x90: return "LANG_WALON";
	case 0x91: return "LANG_CORNISH";
	case 0x92: return "LANG_WELSH";
	case 0x93: return "LANG_BRETON";
	default: return "UNKNOWN";
	}
}

Project: radare2
File: pe.c

static char* _resource_type_str(int type) {
	switch (type) {
	case 1: return "CURSOR";
	case 2: return "BITMAP";
	case 3: return "ICON";
	case 4: return "MENU";
	case 5: return "DIALOG";
	case 6: return "STRING";
	case 7: return "FONTDIR";
	case 8: return "FONT";
	case 9: return "ACCELERATOR";
	case 10: return "RCDATA";
	case 11: return "MESSAGETABLE";
	case 12: return "GROUP_CURSOR";
	case 14: return "GROUP_ICON";
	case 16: return "VERSION";
	case 17: return "DLGINCLUDE";
	case 19: return "PLUGPLAY";
	case 20: return "VXD";
	case 21: return "ANICURSOR";
	case 22: return "ANIICON";
	case 23: return "HTML";
	case 24: return "MANIFEST";
	default: return "UNKNOWN";
	}
}

Project: radare2
File: pe.c

static void _store_resource_sdb(struct PE_(r_bin_pe_obj_t) *bin) {
	RListIter *iter;
	r_pe_resource *rs;
	int index = 0;
	ut64 vaddr = 0;
	char *key;
	Sdb *sdb = sdb_new0 ();
	if (!sdb) {
		return;
	}
	r_list_foreach (bin->resources, iter, rs) {
		key = sdb_fmt ("resource.%d.timestr", index);
		sdb_set (sdb, key, rs->timestr, 0);
		key = sdb_fmt ("resource.%d.vaddr", index);
		vaddr = bin_pe_rva_to_va (bin, rs->data->OffsetToData);
		sdb_num_set (sdb, key, vaddr, 0);
		key = sdb_fmt ("resource.%d.name", index);
		sdb_num_set (sdb, key, rs->name, 0);
		key = sdb_fmt ("resource.%d.size", index);
		sdb_num_set (sdb, key, rs->data->Size, 0);
		key = sdb_fmt ("resource.%d.type", index);
		sdb_set (sdb, key, rs->type, 0);
		key = sdb_fmt ("resource.%d.language", index);
		sdb_set (sdb, key, rs->language, 0);
		index++;
	}
	sdb_ns_set (bin->kv, "pe_resource", sdb);
}

Project: radare2

static char *_time_stamp_to_str(ut32 timeStamp) {
#ifdef _MSC_VER
	time_t rawtime;
	struct tm *tminfo;
	rawtime = (time_t)timeStamp;
	tminfo = localtime (&rawtime);
	return r_str_trim (strdup (asctime (tminfo)));
#else
	struct my_timezone {
		int tz_minuteswest;     /* minutes west of Greenwich */
		int tz_dsttime;         /* type of DST correction */
	} tz;
	struct timeval tv;
	int gmtoff;
	time_t ts = (time_t) timeStamp;
	gettimeofday (&tv, (void*) &tz);
	gmtoff = (int) (tz.tz_minuteswest * 60); // in seconds
	ts += (time_t)gmtoff;
	return r_str_trim (strdup (ctime (&ts)));
#endif
}

Project: radare2

static void bin_pe_get_certificate(struct PE_ (r_bin_pe_obj_t) * bin) {
	ut64 size, vaddr;
	ut8 *data = NULL;
	int len;
	if (!bin || !bin->nt_headers) {
		return;
	}
	bin->cms = NULL;
	size = bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_SECURITY].Size;
	vaddr = bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_SECURITY].VirtualAddress;
	data = calloc (1, size);
	if (!data) {
		return;
	}
	if (vaddr > bin->size || vaddr + size > bin->size) {
		bprintf ("vaddr greater than the file\n");
		free (data);
		return;
	}
	len = r_buf_read_at (bin->b, vaddr + 8, data, size - 8);
	if (len < 1) {
		R_FREE (data);
		return;
	}
	bin->cms = r_pkcs7_parse_cms (data, size);
	bin->is_signed = bin->cms != NULL;
	R_FREE (data);
}

Project: radare2
File: pe.c

int PE_(bin_pe_get_claimed_checksum)(struct PE_(r_bin_pe_obj_t)* bin) {
	if (!bin || !bin->optional_header) {
		return 0;
	}
	return bin->optional_header->CheckSum;
}

Project: radare2
File: pe.c

int PE_(bin_pe_get_overlay)(struct PE_(r_bin_pe_obj_t)* bin, ut64* size) {
	ut64 largest_offset = 0;
	ut64 largest_size = 0;
	*size = 0;
	int i;

	if (!bin) {
		return 0;
	}

	if (bin->optional_header) {
		computeOverlayOffset (
				bin->nt_header_offset+4+sizeof(bin->nt_headers->file_header),
				bin->nt_headers->file_header.SizeOfOptionalHeader,
				bin->size,
				&largest_offset,
				&largest_size);
	}

	struct r_bin_pe_section_t *sects = NULL;
	sects = PE_(r_bin_pe_get_sections) (bin);
	for (i = 0; !sects[i].last; i++) {
		computeOverlayOffset(
				sects[i].paddr,
				sects[i].size,
				bin->size,
				&largest_offset,
				&largest_size
				);
	}

	if (bin->optional_header) {
		for (i = 0; i < PE_IMAGE_DIRECTORY_ENTRIES; i++) {
			if (i == PE_IMAGE_DIRECTORY_ENTRY_SECURITY) {
				continue;
			}

			computeOverlayOffset (
				bin_pe_rva_to_paddr (bin, bin->data_directory[i].VirtualAddress),
				bin->data_directory[i].Size,
				bin->size,
				&largest_offset,
				&largest_size);
		}

	}

	if ((ut64) bin->size > largest_offset + largest_size) {
		*size = bin->size - largest_offset - largest_size;
		free (sects);
		return largest_offset + largest_size;
	}
	free (sects);
	return 0;
}

Project: radare2
File: pe.c

static int bin_pe_init(struct PE_(r_bin_pe_obj_t)* bin) {
	bin->dos_header = NULL;
	bin->nt_headers = NULL;
	bin->section_header = NULL;
	bin->export_directory = NULL;
	bin->import_directory = NULL;
	bin->resource_directory = NULL;
	bin->delay_import_directory = NULL;
	bin->optional_header = NULL;
	bin->data_directory = NULL;
	bin->big_endian = 0;
	if (!bin_pe_init_hdr (bin)) {
		eprintf ("Warning: File is not PE\n");
		return false;
	}
	if (!bin_pe_init_sections (bin)) {
		eprintf ("Warning: Cannot initialize sections\n");
		return false;
	}
	bin_pe_init_imports (bin);
	bin_pe_init_exports (bin);
	bin_pe_init_resource (bin);
	bin_pe_get_certificate(bin);

	bin->big_endian = PE_(r_bin_pe_is_big_endian) (bin);

	bin_pe_init_tls (bin);
	bin_pe_init_clr_hdr (bin);
	bin_pe_init_metadata_hdr (bin);
	bin_pe_init_overlay (bin);
	PE_(bin_pe_parse_resource) (bin);
	bin->relocs = NULL;
	return true;
}

Project: radare2

static int bin_pe_init_clr_hdr(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_(image_data_directory) * clr_dir = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR];
	PE_DWord image_clr_hdr_paddr = bin_pe_rva_to_paddr (bin, clr_dir->VirtualAddress);
	PE_(image_clr_header) * clr_hdr = R_NEW0 (PE_(image_clr_header));
	int rr, len = sizeof (PE_(image_clr_header));

	if (!clr_hdr) {
		return 0;
	}
	rr = r_buf_read_at (bin->b, image_clr_hdr_paddr, (ut8*) (clr_hdr), len);


	if (clr_hdr->HeaderSize != 0x48) {
		free (clr_hdr);
		return 0;
	}
	if (rr != len) {
		free (clr_hdr);
		return 0;
	}

	bin->clr_hdr = clr_hdr;
	return 1;
}

Project: radare2

static int bin_pe_init_exports(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_(image_data_directory) * data_dir_export = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_EXPORT];
	PE_DWord export_dir_paddr = bin_pe_rva_to_paddr (bin, data_dir_export->VirtualAddress);
	if (!export_dir_paddr) {
		return false;
	}
	if (!(bin->export_directory = malloc (sizeof(PE_(image_export_directory))))) {
		r_sys_perror ("malloc (export directory)");
		return false;
	}
	if (r_buf_read_at (bin->b, export_dir_paddr, (ut8*) bin->export_directory, sizeof (PE_(image_export_directory))) == -1) {
		bprintf ("Warning: read (export directory)\n");
		free (bin->export_directory);
		bin->export_directory = NULL;
		return false;
	}
	return true;
}

Project: radare2

static int bin_pe_init_metadata_hdr(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_DWord metadata_directory = bin->clr_hdr? bin_pe_rva_to_paddr (bin, bin->clr_hdr->MetaDataDirectoryAddress): 0;
	PE_(image_metadata_header) * metadata = R_NEW0 (PE_(image_metadata_header));
	int rr;
	if (!metadata) {
		return 0;
	}
	if (!metadata_directory) {
		free (metadata);
		return 0;
	}


	rr = r_buf_fread_at (bin->b, metadata_directory,
		(ut8*) metadata, bin->big_endian? "1I2S": "1i2s", 1);
	if (rr < 1) {
		goto fail;
	}

	rr = r_buf_fread_at (bin->b, metadata_directory + 8,
		(ut8*) (&metadata->Reserved), bin->big_endian? "1I": "1i", 1);
	if (rr < 1) {
		goto fail;
	}

	rr = r_buf_fread_at (bin->b, metadata_directory + 12,
		(ut8*) (&metadata->VersionStringLength), bin->big_endian? "1I": "1i", 1);
	if (rr < 1) {
		goto fail;
	}

	eprintf ("Metadata Signature: 0x%"PFMT64x" 0x%"PFMT64x" %d\n",
		(ut64)metadata_directory, (ut64)metadata->Signature, (int)metadata->VersionStringLength);

	int len = metadata->VersionStringLength; // XXX: dont trust this length
	if (len > 0) {
		metadata->VersionString = calloc (1, len + 1);
		if (!metadata->VersionString) {
			goto fail;
		}

		rr = r_buf_read_at (bin->b, metadata_directory + 16, (ut8*)(metadata->VersionString),  len);
		if (rr != len) {
			eprintf ("Warning: read (metadata header) - cannot parse version string\n");
			free (metadata->VersionString);
			free (metadata);
			return 0;
		}
		eprintf (".NET Version: %s\n", metadata->VersionString);
	}

	rr = r_buf_fread_at (bin->b, metadata_directory + 16 + metadata->VersionStringLength,
		(ut8*) (&metadata->Flags), bin->big_endian? "2S": "2s", 1);

	if (rr < 1) {
		goto fail;
	}

	eprintf ("Number of Metadata Streams: %d\n", metadata->NumberOfStreams);
	bin->metadata_header = metadata;


	int start_of_stream = metadata_directory + 20 + metadata->VersionStringLength;
	PE_(image_metadata_stream) * stream;
	PE_(image_metadata_stream) **streams = calloc (sizeof (PE_(image_metadata_stream)*), metadata->NumberOfStreams);
	if (!streams) {
		goto fail;
	}
	int count = 0;

	while (count < metadata->NumberOfStreams) {
		stream = R_NEW0 (PE_(image_metadata_stream));
		if (!stream) {
			free (streams);
			goto fail;
		}

		if (r_buf_fread_at (bin->b, start_of_stream, (ut8*) stream, bin->big_endian? "2I": "2i", 1) < 1) {
			free (stream);
			free (streams);
			goto fail;
		}
		eprintf ("DirectoryAddress: %x Size: %x\n", stream->Offset, stream->Size);
		char* stream_name = calloc (1, MAX_METADATA_STRING_LENGTH + 1);

		if (!stream_name) {
			free (stream);
			free (streams);
			goto fail;
		}

		if (r_buf_size (bin->b) < (start_of_stream + 8 + MAX_METADATA_STRING_LENGTH)) {
			free (stream_name);
			free (stream);
			free (streams);
			goto fail;
		}
		int c = bin_pe_read_metadata_string (stream_name,
			(char *)(bin->b->buf + start_of_stream + 8));
		if (c == 0) {
			free (stream_name);
			free (stream);
			free (streams);
			goto fail;
		}
		eprintf ("Stream name: %s %d\n", stream_name, c);
		stream->Name = stream_name;
		streams[count] = stream;
		start_of_stream += 8 + c;
		count += 1;
	}
	bin->streams = streams;
	return 1;
fail:
	eprintf ("Warning: read (metadata header)\n");
	free (metadata);
	return 0;
}

Project: radare2
File: pe.c

static int bin_pe_init_overlay(struct PE_(r_bin_pe_obj_t)* bin) {
	ut64 pe_overlay_size;
	ut64 pe_overlay_offset = PE_(bin_pe_get_overlay) (bin, &pe_overlay_size);
	if (pe_overlay_offset) {
		sdb_num_set (bin->kv, "pe_overlay.offset", pe_overlay_offset, 0);
		sdb_num_set (bin->kv, "pe_overlay.size", pe_overlay_size, 0);
	}
	return 0;
}

Project: radare2
File: pe.c

static int bin_pe_init_resource(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_(image_data_directory) * resource_dir = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_RESOURCE];
	PE_DWord resource_dir_paddr = bin_pe_rva_to_paddr (bin, resource_dir->VirtualAddress);
	if (!resource_dir_paddr) {
		return false;
	}

	bin->resources = r_list_newf ((RListFree)_free_resources);
	if (!bin->resources) {
		return false;
	}
	if (!(bin->resource_directory = malloc (sizeof(*bin->resource_directory)))) {
		r_sys_perror ("malloc (resource directory)");
		return false;
	}
	if (r_buf_read_at (bin->b, resource_dir_paddr, (ut8*) bin->resource_directory,
		sizeof (*bin->resource_directory)) != sizeof (*bin->resource_directory)) {
		bprintf ("Warning: read (resource directory)\n");
		free (bin->resource_directory);
		bin->resource_directory = NULL;
		return false;
	}
	bin->resource_directory_offset = resource_dir_paddr;
	return true;
}

Project: radare2

static int bin_pe_init_sections(struct PE_(r_bin_pe_obj_t)* bin) {
	bin->num_sections = bin->nt_headers->file_header.NumberOfSections;
	int sections_size;
	if (bin->num_sections < 1) {
		return true;
	}
	sections_size = sizeof (PE_(image_section_header)) * bin->num_sections;
	if (sections_size > bin->size) {
		sections_size = bin->size;
		bin->num_sections = bin->size / sizeof (PE_(image_section_header));
	}
	if (!(bin->section_header = malloc (sections_size))) {
		r_sys_perror ("malloc (section header)");
		goto out_error;
	}
	bin->section_header_offset = bin->dos_header->e_lfanew + 4 + sizeof (PE_(image_file_header)) +
		bin->nt_headers->file_header.SizeOfOptionalHeader;
	if (r_buf_read_at (bin->b, bin->section_header_offset,
		(ut8*) bin->section_header, sections_size) == -1) {
		bprintf ("Warning: read (sections)\n");
		R_FREE (bin->section_header);
		goto out_error;
	}
#if 0
	Each symbol table entry includes a name, storage class, type, value and section number.Short names (8 characters or fewer) are stored directly in the symbol table;
	longer names are stored as an paddr into the string table at the end of the COFF object.

	================================================================
	COFF SYMBOL TABLE RECORDS (18 BYTES)
	================================================================
	record
	paddr

	struct symrec {
		union {
			char string[8]; // short name
			struct {
				ut32 seros;
				ut32 stridx;
			} stridx;
		} name;
		ut32 value;
		ut16 secnum;
		ut16 symtype;
		ut8 symclass;
		ut8 numaux;
	}
	------------------------------------------------------ -
	0 | 8 - char symbol name |
	| or 32 - bit zeroes followed by 32 - bit |
	| index into string table |
	------------------------------------------------------ -
	8 | symbol value |
	------------------------------------------------------ -
	0Ch | section number | symbol type |
	------------------------------------------------------ -
	10h | sym class | num aux |
	-------------------------- -
	12h

#endif
	return true;
out_error:
	bin->num_sections = 0;
	return false;
}

Project: radare2
File: pe.c

R_API void PE_(bin_pe_parse_resource)(struct PE_(r_bin_pe_obj_t) *bin) {
	int index = 0;
	ut64 off = 0, rsrc_base = bin->resource_directory_offset;
	Pe_image_resource_directory *rs_directory = bin->resource_directory;
	ut32 curRes = 0;
	int totalRes = 0;
	SdbHash *dirs = sdb_ht_new (); //to avoid infinite loops
	if (!dirs) {
		return;
	}
	if (!rs_directory) {
		sdb_ht_free (dirs);
		return;
	}
	curRes = rs_directory->NumberOfNamedEntries;
	totalRes = curRes + rs_directory->NumberOfIdEntries;
	if (totalRes > R_PE_MAX_RESOURCES) {
		eprintf ("Error parsing resource directory\n");
		sdb_ht_free (dirs);
		return;
	}
	for (index = 0; index < totalRes; index++) {
		Pe_image_resource_directory_entry typeEntry;
		off = rsrc_base + sizeof (*rs_directory) + index * sizeof (typeEntry);
		sdb_ht_insert (dirs, sdb_fmt ("0x%08"PFMT64x, off), "1");
		if (off > bin->size || off + sizeof(typeEntry) > bin->size) {
			break;
		}
		if (r_buf_read_at (bin->b, off, (ut8*)&typeEntry, sizeof(typeEntry)) < 1) {
			eprintf ("Warning: read resource  directory entry\n");
			break;
		}
		if (typeEntry.u2.s.DataIsDirectory) {
			Pe_image_resource_directory identEntry;
			off = rsrc_base + typeEntry.u2.s.OffsetToDirectory;
			int len = r_buf_read_at (bin->b, off, (ut8*)&identEntry, sizeof(identEntry));
			if (len < 1 || len != sizeof (identEntry)) {
				eprintf ("Warning: parsing resource directory\n");
			}
			_parse_resource_directory (bin, &identEntry, typeEntry.u2.s.OffsetToDirectory, typeEntry.u1.Id, 0, dirs);
		}
	}
	sdb_ht_free (dirs);
	_store_resource_sdb (bin);
}

Project: radare2
File: pe.c

static int bin_pe_read_metadata_string(char* to, char* from) {
	int covered = 0;
	while (covered < MAX_METADATA_STRING_LENGTH) {
		to[covered] = from[covered];
		if (from[covered] == '\0') {
			covered += 1;
			break;
		}
		covered++;
	}
	while (covered % 4 != 0) { covered++; }
	return covered;
}

Project: radare2
File: pe.c

static PE_DWord bin_pe_rva_to_va(RBinPEObj* bin, PE_DWord rva) {
	return PE_(r_bin_pe_get_image_base) (bin) + rva;
}

Project: radare2
File: pe.c

static void bin_pe_store_tls_callbacks(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord callbacks) {
	PE_DWord paddr, haddr;
	int count = 0;
	PE_DWord addressOfTLSCallback = 1;
	char* key;

	while (addressOfTLSCallback != 0) {
		if (r_buf_read_at (bin->b, callbacks, (ut8*) &addressOfTLSCallback, sizeof(addressOfTLSCallback)) != sizeof (addressOfTLSCallback)) {
			bprintf ("Warning: read (tls_callback)\n");
			return;
		}
		if (!addressOfTLSCallback) {
			break;
		}
		if (bin->optional_header->SizeOfImage) {
			int rva_callback = bin_pe_va_to_rva (bin, (PE_DWord) addressOfTLSCallback);
			if (rva_callback > bin->optional_header->SizeOfImage) {
				break;
			}
		}
		key = sdb_fmt ("pe.tls_callback%d_vaddr", count);
		sdb_num_set (bin->kv, key, addressOfTLSCallback, 0);
		key = sdb_fmt ("pe.tls_callback%d_paddr", count);
		paddr = bin_pe_rva_to_paddr (bin, bin_pe_va_to_rva (bin, (PE_DWord) addressOfTLSCallback));
		sdb_num_set (bin->kv, key, paddr,                0);
		key = sdb_fmt ("pe.tls_callback%d_haddr", count);
		haddr = callbacks;
		sdb_num_set (bin->kv, key, haddr,                0);
		count++;
		callbacks += sizeof (addressOfTLSCallback);
	}
}

Project: radare2
File: pe.c

static PE_DWord bin_pe_va_to_rva(RBinPEObj* bin, PE_DWord va) {
	ut64 imageBase = PE_(r_bin_pe_get_image_base) (bin);
	if (va < imageBase) {
		return va;
	}
	return va - imageBase;
}

Project: radare2

struct r_bin_pe_addr_t *PE_(check_mingw) (struct PE_(r_bin_pe_obj_t) *bin) {
	struct r_bin_pe_addr_t* entry;
	int sw = 0;
	ut8 b[1024];
	int n = 0;
	if (!bin || !bin->b) {
		return 0LL;
	}
	entry = PE_(r_bin_pe_get_entrypoint) (bin);
	ZERO_FILL (b);
	if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) < 0) {
		bprintf ("Warning: Cannot read entry at 0x%08"PFMT64x "\n", entry->paddr);
		free (entry);
		return NULL;
	}
	if (b[0] == 0x55 && b[1] == 0x89 && b[3] == 0x83 && b[6] == 0xc7 && b[13] == 0xff && b[19] == 0xe8) {
		const st32 jmp_dst = (st32) r_read_le32 (&b[20]);
		entry->paddr += (5 + 19 + jmp_dst);
		entry->vaddr += (5 + 19 + jmp_dst);
		sw = 1;
	}
	if (b[0] == 0x83 && b[3] == 0xc7 && b[10] == 0xff && b[16] == 0xe8) {
		const st32 jmp_dst = (st32) r_read_le32 (&b[17]);
		entry->paddr += (5 + 16 + jmp_dst);
		entry->vaddr += (5 + 16 + jmp_dst);
		sw = 1;
	}
	if (b[0] == 0x83 && b[3] == 0xc7 && b[13] == 0xe8 && b[18] == 0x83 && b[21] == 0xe9) {
		const st32 jmp_dst = (st32) r_read_le32 (&b[22]);
		entry->paddr += (5 + 21 + jmp_dst);
		entry->vaddr += (5 + 21 + jmp_dst);
		sw = 1;
	}
	if (sw) {
		if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) > 0) {
			for (n = 0; n < sizeof (b) - 12; n++) {
				if (b[n] == 0xa1 && b[n + 5] == 0x89 && b[n + 8] == 0xe8) {
					const st32 call_dst = (st32) r_read_le32 (&b[n + 9]);
					entry->paddr += (n + 5 + 8 + call_dst);
					entry->vaddr += (n + 5 + 8 + call_dst);
					return entry;
				}
			}
		}
	}
	free (entry);
	return NULL;
}

Project: radare2

struct r_bin_pe_addr_t *PE_(check_unknow) (struct PE_(r_bin_pe_obj_t) *bin) {
	struct r_bin_pe_addr_t *entry;
	if (!bin || !bin->b) {
		return 0LL;
	}
	ut8 *b = calloc (1, 512);
	if (!b) {
		return NULL;
	}
	entry = PE_ (r_bin_pe_get_entrypoint) (bin);
	if (r_buf_read_at (bin->b, entry->paddr, b, 512) < 1) {
		bprintf ("Warning: Cannot read entry at 0x%08"PFMT64x"\n", entry->paddr);
		free (entry);
		free (b);
		return NULL;
	}
	/* Decode the jmp instruction, this gets the address of the 'main'
	   function for PE produced by a compiler whose name someone forgot to
	   write down. */
	if (b[367] == 0xe8) {
		const st32 jmp_dst = (st32) r_read_le32 (&b[368]);
		entry->paddr += 367 + 5 + jmp_dst;
		entry->vaddr += 367 + 5 + jmp_dst;
		free (b);
		return entry;
	}
	int i;
	for (i = 0; i < 512 - 16 ; i++) {
		if (!memcmp (b + i, "\xff\x15", 2)) {
			if (b[i+6] == 0x50) {
				if (b[i+7] == 0xe8) {
					const st32 call_dst = (st32) r_read_le32 (&b[i + 8]);
					entry->paddr = entry->vaddr - entry->paddr;
					entry->vaddr += (i + 7 + 5 + (long)call_dst);
					entry->paddr += entry->vaddr;
					free (b);
					return entry;
				}
			}
		}
	}
	free (entry);
	free (b);
	return NULL;
}

Project: radare2
File: pe.c

static void computeOverlayOffset(ut64 offset, ut64 size, ut64 file_size, ut64* largest_offset, ut64* largest_size) {
	if (offset + size <= file_size && offset + size > (*largest_offset + *largest_size)) {
		*largest_offset = offset;
		*largest_size = size;
	}
}

Project: radare2
File: pe.c

static void free_String(String* string) {
	if (string) {
		free (string->szKey);
		free (string->Value);
		free (string);
	}
}

Project: radare2
File: pe.c

static void free_StringFileInfo(StringFileInfo* stringFileInfo) {
	if (stringFileInfo) {
		free (stringFileInfo->szKey);
		if (stringFileInfo->Children) {
			ut32 childrenSFI = 0;
			for (; childrenSFI < stringFileInfo->numOfChildren; childrenSFI++) {
				free_StringTable (stringFileInfo->Children[childrenSFI]);
			}
			free (stringFileInfo->Children);
		}
		free (stringFileInfo);
	}
}

Project: radare2
File: pe.c

static void free_StringTable(StringTable* stringTable) {
	if (stringTable) {
		free (stringTable->szKey);
		if (stringTable->Children) {
			ut32 childrenST = 0;
			for (; childrenST < stringTable->numOfChildren; childrenST++) {
				free_String (stringTable->Children[childrenST]);
			}
			free (stringTable->Children);
		}
		free (stringTable);
	}
}

Project: radare2
File: pe.c

static void free_VS_VERSIONINFO(PE_VS_VERSIONINFO* vs_VersionInfo) {
	if (vs_VersionInfo) {
		free (vs_VersionInfo->szKey);
		free (vs_VersionInfo->Value);
		free_VarFileInfo (vs_VersionInfo->varFileInfo);
		free_StringFileInfo (vs_VersionInfo->stringFileInfo);
		free (vs_VersionInfo);
	}
}

Project: radare2
File: pe.c

void PE_(free_VS_VERSIONINFO)(PE_VS_VERSIONINFO * vs_VersionInfo) {
	free_VS_VERSIONINFO (vs_VersionInfo);
}

Project: radare2
File: pe.c

static void free_VarFileInfo(VarFileInfo* varFileInfo) {
	if (varFileInfo) {
		free (varFileInfo->szKey);
		if (varFileInfo->Children) {
			ut32 children = 0;
			for (; children < varFileInfo->numOfChildren; children++) {
				free_Var (varFileInfo->Children[children]);
			}
			free (varFileInfo->Children);
		}
		free (varFileInfo);
	}
}

Project: radare2
File: pe.c

static void free_cv_nb10_header(SCV_NB10_HEADER* cv_nb10_header) {
	R_FREE (cv_nb10_header->file_name);
}

Project: radare2
File: pe.c

static void free_rsdr_hdr(SCV_RSDS_HEADER* rsds_hdr) {
	R_FREE (rsds_hdr->file_name);
}

Project: radare2
File: pe.c

static bool get_rsds(ut8* dbg_data, int dbg_data_len, SCV_RSDS_HEADER* res) {
	const int rsds_sz = 4 + sizeof (SGUID) + 4;
	if (dbg_data_len < rsds_sz) {
		return false;
	}
	memcpy (res, dbg_data, rsds_sz);
	res->file_name = (ut8*) strdup ((const char*) dbg_data + rsds_sz);
	return true;
}

Project: radare2
File: pe.c

static void init_cv_nb10_header(SCV_NB10_HEADER* cv_nb10_header) {
	memset (cv_nb10_header, 0, sizeof (SCV_NB10_HEADER));
	cv_nb10_header->free = (void (*)(struct SCV_NB10_HEADER*))free_cv_nb10_header;
}

Project: radare2
File: pe.c

static void init_rsdr_hdr(SCV_RSDS_HEADER* rsds_hdr) {
	memset (rsds_hdr, 0, sizeof (SCV_RSDS_HEADER));
	rsds_hdr->free = (void (*)(struct SCV_RSDS_HEADER*))free_rsdr_hdr;
}

Project: radare2
File: pe.c

static inline int is_arm(struct PE_(r_bin_pe_obj_t)* bin) {
	switch (bin->nt_headers->file_header.Machine) {
	case PE_IMAGE_FILE_MACHINE_RPI2: // 462
	case PE_IMAGE_FILE_MACHINE_ARM:
	case PE_IMAGE_FILE_MACHINE_THUMB:
		return 1;
	}
	return 0;
}

Project: radare2
File: pe.c

static inline int is_thumb(struct PE_(r_bin_pe_obj_t)* bin) {
	return bin->nt_headers->optional_header.AddressOfEntryPoint & 1;
}