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

static Sdb* Pe_r_bin_store_string_table(StringTable* stringTable) {
	char key[20];
	char* encodedKey = NULL;
	int i = 0;
	Sdb* sdb = NULL;
	if (!stringTable) {
		return NULL;
	}
	sdb = sdb_new0 ();
	if (!sdb) {
		return NULL;
	}
	encodedKey = sdb_encode ((unsigned char*) stringTable->szKey, EIGHT_HEX_DIG_UTF_16_LEN);
	if (!encodedKey) {
		sdb_free (sdb);
		return NULL;
	}
	sdb_set (sdb, "key", encodedKey, 0);
	free (encodedKey);
	for (; i < stringTable->numOfChildren; i++) {
		snprintf (key, 20, "string%d", i);
		sdb_ns_set (sdb, key, Pe_r_bin_store_string (stringTable->Children[i]));
	}
	return sdb;
}

Project: radare2
File: pe.c

static Sdb* Pe_r_bin_store_var(Var* var) {
	unsigned int i = 0;
	char key[20];
	Sdb* sdb = NULL;
	if (var) {
		sdb = sdb_new0 ();
		if (sdb) {
			for (; i < var->numOfValues; i++) {
				snprintf (key, 20, "%d", i);
				sdb_num_set (sdb, key, var->Value[i], 0);
			}
		}
	}
	return sdb;
}

Project: radare2

static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_resource_directory *dir, ut64 offDir, int type, int id, SdbHash *dirs) {
	int index = 0;
	ut32 totalRes = dir->NumberOfNamedEntries + dir->NumberOfIdEntries;
	ut64 rsrc_base = bin->resource_directory_offset;
	ut64 off;
	if (totalRes > R_PE_MAX_RESOURCES) {
		return;
	}
	for (index = 0; index < totalRes; index++) {
		Pe_image_resource_directory_entry entry;
		off = rsrc_base + offDir + sizeof(*dir) + index * sizeof(entry);
		char *key = sdb_fmt ("0x%08"PFMT64x, off);
		if (sdb_ht_find (dirs, key, NULL)) {
			break;
		}
		sdb_ht_insert (dirs, key, "1");
		if (off > bin->size || off + sizeof (entry) > bin->size) {
			break;
		}
		if (r_buf_read_at (bin->b, off, (ut8*)&entry, sizeof(entry)) < 1) {
			eprintf ("Warning: read resource entry\n");
			break;
		}
		if (entry.u2.s.DataIsDirectory) {
			Pe_image_resource_directory identEntry;
			off = rsrc_base + entry.u2.s.OffsetToDirectory;
			int len = r_buf_read_at (bin->b, off, (ut8*) &identEntry, sizeof (identEntry));
			if (len < 1 || len != sizeof (Pe_image_resource_directory)) {
				eprintf ("Warning: parsing resource directory\n");
			}
			_parse_resource_directory (bin, &identEntry,
				entry.u2.s.OffsetToDirectory, type, entry.u1.Id, dirs);
			continue;
		}

		Pe_image_resource_data_entry *data = R_NEW0 (Pe_image_resource_data_entry);
		if (!data) {
			break;
		}
		off = rsrc_base + entry.u2.OffsetToData;
		if (off > bin->size || off + sizeof (data) > bin->size) {
			free (data);
			break;
		}
		if (r_buf_read_at (bin->b, off, (ut8*)data, sizeof (*data)) != sizeof (*data)) {
			eprintf ("Warning: read (resource data entry)\n");
			free (data);
			break;
		}
		if (type == PE_RESOURCE_ENTRY_VERSION) {
			char key[64];
			int counter = 0;
			Sdb *sdb = sdb_new0 ();
			if (!sdb) {
				free (data);
				sdb_free (sdb);
				continue;
			}
			PE_DWord data_paddr = bin_pe_rva_to_paddr (bin, data->OffsetToData);
			if (!data_paddr) {
				bprintf ("Warning: bad RVA in resource data entry\n");
				free (data);
				sdb_free (sdb);
				continue;
			}
			PE_DWord cur_paddr = data_paddr;
			if ((cur_paddr & 0x3) != 0) {
				bprintf ("Warning: not aligned version info address\n");
				free (data);
				sdb_free (sdb);
				continue;
			}
			while (cur_paddr < (data_paddr + data->Size) && cur_paddr < bin->size) {
				PE_VS_VERSIONINFO* vs_VersionInfo = Pe_r_bin_pe_parse_version_info (bin, cur_paddr);
				if (vs_VersionInfo) {
					snprintf (key, 30, "VS_VERSIONINFO%d", counter++);
					sdb_ns_set (sdb, key, Pe_r_bin_store_resource_version_info (vs_VersionInfo));
				} else {
					break;
				}
				if (vs_VersionInfo->wLength < 1) {
					break;
				}
				cur_paddr += vs_VersionInfo->wLength;
				free_VS_VERSIONINFO (vs_VersionInfo);
				align32 (cur_paddr);
			}
			sdb_ns_set (bin->kv, "vs_version_info", sdb);
		}
		r_pe_resource *rs = R_NEW0 (r_pe_resource);
		if (!rs) {
			free (data);
			break;
		}
		rs->timestr = _time_stamp_to_str (dir->TimeDateStamp);
		rs->type = strdup (_resource_type_str (type));
		rs->language = strdup (_resource_lang_str (entry.u1.Name & 0x3ff));
		rs->data = data;
		rs->name = id;
		r_list_append (bin->resources, rs);
	}
}

Project: radare2

int PE_(bin_pe_get_actual_checksum)(struct PE_(r_bin_pe_obj_t)* bin) {
	int i, j, checksum_offset = 0;
	ut8* buf = NULL;
	ut64 computed_cs = 0;
	int remaining_bytes;
	int shift;
	ut32 cur;
	if (!bin || !bin->nt_header_offset) {
		return 0;
	}
	buf = bin->b->buf;
	checksum_offset = bin->nt_header_offset + 4 + sizeof(PE_(image_file_header)) + 0x40;
	for (i = 0; i < bin->size / 4; i++) {
		cur = r_read_le32 (&buf[i * 4]);

		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);
		}
	}

	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);
		}
	}

	computed_cs = (computed_cs & 0xFFFF) + (computed_cs >> 16);
	computed_cs = (computed_cs) + (computed_cs >> 16);
	computed_cs = (computed_cs & 0xFFFF);

	computed_cs += bin->size;
	return computed_cs;
}

Project: radare2

static int bin_pe_init_hdr(struct PE_(r_bin_pe_obj_t)* bin) {
	if (!(bin->dos_header = malloc (sizeof(PE_(image_dos_header))))) {
		r_sys_perror ("malloc (dos header)");
		return false;
	}
	if (r_buf_read_at (bin->b, 0, (ut8*) bin->dos_header, sizeof(PE_(image_dos_header))) == -1) {
		bprintf ("Warning: read (dos header)\n");
		return false;
	}
	sdb_num_set (bin->kv, "pe_dos_header.offset", 0, 0);
	sdb_set (bin->kv, "pe_dos_header.format", "[2]zwwwwwwwwwwwww[4]www[10]wx"
		" e_magic e_cblp e_cp e_crlc e_cparhdr e_minalloc e_maxalloc"
		" e_ss e_sp e_csum e_ip e_cs e_lfarlc e_ovno e_res e_oemid"
		" e_oeminfo e_res2 e_lfanew", 0);
	if (bin->dos_header->e_lfanew > (unsigned int) bin->size) {
		bprintf ("Invalid e_lfanew field\n");
		return false;
	}
	if (!(bin->nt_headers = malloc (sizeof (PE_(image_nt_headers))))) {
		r_sys_perror ("malloc (nt header)");
		return false;
	}
	bin->nt_header_offset = bin->dos_header->e_lfanew;
	if (r_buf_read_at (bin->b, bin->dos_header->e_lfanew, (ut8*) bin->nt_headers, sizeof (PE_(image_nt_headers))) < -1) {
		bprintf ("Warning: read (dos header)\n");
		return false;
	}
	sdb_set (bin->kv, "pe_magic.cparse",     "enum pe_magic { IMAGE_NT_OPTIONAL_HDR32_MAGIC=0x10b, IMAGE_NT_OPTIONAL_HDR64_MAGIC=0x20b, IMAGE_ROM_OPTIONAL_HDR_MAGIC=0x107 };", 0);
	sdb_set (bin->kv, "pe_subsystem.cparse", "enum pe_subsystem { IMAGE_SUBSYSTEM_UNKNOWN=0, IMAGE_SUBSYSTEM_NATIVE=1, IMAGE_SUBSYSTEM_WINDOWS_GUI=2, "
		" IMAGE_SUBSYSTEM_WINDOWS_CUI=3, IMAGE_SUBSYSTEM_OS2_CUI=5, IMAGE_SUBSYSTEM_POSIX_CUI=7, IMAGE_SUBSYSTEM_WINDOWS_CE_GUI=9, "
		" IMAGE_SUBSYSTEM_EFI_APPLICATION=10, IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER=11, IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER=12, "
		" IMAGE_SUBSYSTEM_EFI_ROM=13, IMAGE_SUBSYSTEM_XBOX=14, IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION=16 };", 0);
	sdb_set (bin->kv, "pe_dllcharacteristics.cparse", "enum pe_dllcharacteristics { IMAGE_LIBRARY_PROCESS_INIT=0x0001, IMAGE_LIBRARY_PROCESS_TERM=0x0002, "
		" IMAGE_LIBRARY_THREAD_INIT=0x0004, IMAGE_LIBRARY_THREAD_TERM=0x0008, IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA=0x0020, "
		" IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE=0x0040, IMAGE_DLLCHARACTERISTICS_FORCE_INTEGRITY=0x0080, "
		" IMAGE_DLLCHARACTERISTICS_NX_COMPAT=0x0100, IMAGE_DLLCHARACTERISTICS_NO_ISOLATION=0x0200,IMAGE_DLLCHARACTERISTICS_NO_SEH=0x0400, "
		" IMAGE_DLLCHARACTERISTICS_NO_BIND=0x0800, IMAGE_DLLCHARACTERISTICS_APPCONTAINER=0x1000, IMAGE_DLLCHARACTERISTICS_WDM_DRIVER=0x2000, "
		" IMAGE_DLLCHARACTERISTICS_GUARD_CF=0x4000, IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE=0x8000};", 0);
#if R_BIN_PE64
	sdb_num_set (bin->kv, "pe_nt_image_headers64.offset", bin->dos_header->e_lfanew, 0);
	sdb_set (bin->kv, "pe_nt_image_headers64.format",      "[4]z?? signature (pe_image_file_header)fileHeader (pe_image_optional_header64)optionalHeader", 0);
	sdb_set (bin->kv, "pe_image_optional_header64.format", "[2]Ebbxxxxxqxxwwwwwwxxxx[2]E[2]Bqqqqxx[16]?"
		" (pe_magic)magic majorLinkerVersion minorLinkerVersion sizeOfCode sizeOfInitializedData"
		" sizeOfUninitializedData addressOfEntryPoint baseOfCode imageBase"
		" sectionAlignment fileAlignment majorOperatingSystemVersion minorOperatingSystemVersion"
		" majorImageVersion minorImageVersion majorSubsystemVersion minorSubsystemVersion"
		" win32VersionValue sizeOfImage sizeOfHeaders checkSum (pe_subsystem)subsystem (pe_dllcharacteristics)dllCharacteristics"
		" sizeOfStackReserve sizeOfStackCommit sizeOfHeapReserve sizeOfHeapCommit loaderFlags"
		" numberOfRvaAndSizes (pe_image_data_directory)dataDirectory", 0);
#else
	sdb_num_set (bin->kv, "pe_nt_image_headers32.offset", bin->dos_header->e_lfanew, 0);
	sdb_set (bin->kv, "pe_nt_image_headers32.format",      "[4]z?? signature (pe_image_file_header)fileHeader (pe_image_optional_header32)optionalHeader", 0);
	sdb_set (bin->kv, "pe_image_optional_header32.format", "[2]Ebbxxxxxxxxxwwwwwwxxxx[2]E[2]Bxxxxxx[16]?"
		" (pe_magic)magic majorLinkerVersion minorLinkerVersion sizeOfCode sizeOfInitializedData"
		" sizeOfUninitializedData addressOfEntryPoint baseOfCode baseOfData imageBase"
		" sectionAlignment fileAlignment majorOperatingSystemVersion minorOperatingSystemVersion"
		" majorImageVersion minorImageVersion majorSubsystemVersion minorSubsystemVersion"
		" win32VersionValue sizeOfImage sizeOfHeaders checkSum (pe_subsystem)subsystem (pe_dllcharacteristics)dllCharacteristics"
		" sizeOfStackReserve sizeOfStackCommit sizeOfHeapReserve sizeOfHeapCommit loaderFlags numberOfRvaAndSizes"
		" (pe_image_data_directory)dataDirectory", 0);
#endif
	sdb_set (bin->kv, "pe_machine.cparse",         "enum pe_machine { IMAGE_FILE_MACHINE_I386=0x014c, IMAGE_FILE_MACHINE_IA64=0x0200, IMAGE_FILE_MACHINE_AMD64=0x8664 };", 0);
	sdb_set (bin->kv, "pe_characteristics.cparse", "enum pe_characteristics { "
		" IMAGE_FILE_RELOCS_STRIPPED=0x0001, IMAGE_FILE_EXECUTABLE_IMAGE=0x0002, IMAGE_FILE_LINE_NUMS_STRIPPED=0x0004, "
		" IMAGE_FILE_LOCAL_SYMS_STRIPPED=0x0008, IMAGE_FILE_AGGRESIVE_WS_TRIM=0x0010, IMAGE_FILE_LARGE_ADDRESS_AWARE=0x0020, "
		" IMAGE_FILE_BYTES_REVERSED_LO=0x0080, IMAGE_FILE_32BIT_MACHINE=0x0100, IMAGE_FILE_DEBUG_STRIPPED=0x0200, "
		" IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP=0x0400, IMAGE_FILE_NET_RUN_FROM_SWAP=0x0800, IMAGE_FILE_SYSTEM=0x1000, "
		" IMAGE_FILE_DLL=0x2000, IMAGE_FILE_UP_SYSTEM_ONLY=0x4000, IMAGE_FILE_BYTES_REVERSED_HI=0x8000 };", 0);
	sdb_set (bin->kv, "pe_image_file_header.format",    "[2]Ewtxxw[2]B"
		" (pe_machine)machine numberOfSections timeDateStamp pointerToSymbolTable"
		" numberOfSymbols sizeOfOptionalHeader (pe_characteristics)characteristics", 0);
	sdb_set (bin->kv, "pe_image_data_directory.format", "xx virtualAddress size",0);

	{
		sdb_num_set (bin->kv, "image_file_header.TimeDateStamp", bin->nt_headers->file_header.TimeDateStamp, 0);
		char *timestr = _time_stamp_to_str (bin->nt_headers->file_header.TimeDateStamp);
		sdb_set_owned (bin->kv, "image_file_header.TimeDateStamp_string", timestr, 0);
	}
	bin->optional_header = &bin->nt_headers->optional_header;
	bin->data_directory = (PE_(image_data_directory*)) & bin->optional_header->DataDirectory;

	if (strncmp ((char*) &bin->dos_header->e_magic, "MZ", 2) ||
	(strncmp ((char*) &bin->nt_headers->Signature, "PE", 2) &&
	/* Check also for Phar Lap TNT DOS extender PL executable */
	strncmp ((char*) &bin->nt_headers->Signature, "PL", 2))) {
		return false;
	}
	return true;
}

Project: radare2

static int bin_pe_init_imports(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_(image_data_directory) * data_dir_import = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_IMPORT];
	PE_(image_data_directory) * data_dir_delay_import = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT];

	PE_DWord import_dir_paddr = bin_pe_rva_to_paddr (bin, data_dir_import->VirtualAddress);
	PE_DWord import_dir_offset = bin_pe_rva_to_paddr (bin, data_dir_import->VirtualAddress);
	PE_DWord delay_import_dir_offset = data_dir_delay_import
	? bin_pe_rva_to_paddr (bin, data_dir_delay_import->VirtualAddress)
					: 0;

	PE_(image_import_directory) * import_dir = NULL;
	PE_(image_import_directory) * new_import_dir = NULL;
	PE_(image_import_directory) * curr_import_dir = NULL;

	PE_(image_delay_import_directory) * delay_import_dir = NULL;
	PE_(image_delay_import_directory) * curr_delay_import_dir = NULL;

	int dir_size = sizeof(PE_(image_import_directory));
	int delay_import_size = sizeof(PE_(image_delay_import_directory));
	int indx = 0;
	int rr, count = 0;
	int import_dir_size = data_dir_import->Size;
	int delay_import_dir_size = data_dir_delay_import->Size;
	if (!import_dir_size) {
		import_dir_size = data_dir_import->Size = 0xffff;
	}
	if (!delay_import_dir_size) {
		delay_import_dir_size = data_dir_delay_import->Size = 0xffff;
	}
	int maxidsz = R_MIN ((PE_DWord) bin->size, import_dir_offset + import_dir_size);
	maxidsz -= import_dir_offset;
	if (maxidsz < 0) {
		maxidsz = 0;
	}

	free (bin->import_directory);
	bin->import_directory = NULL;
	if (import_dir_paddr != 0) {
		if (import_dir_size < 1 || import_dir_size > maxidsz) {
			bprintf ("Warning: Invalid import directory size: 0x%x is now 0x%x\n", import_dir_size, maxidsz);
			import_dir_size = maxidsz;
		}
		bin->import_directory_offset = import_dir_offset;
		count = 0;
		do {
			indx++;
			if (((2 + indx) * dir_size) > import_dir_size) {
				break; //goto fail;
			}
			new_import_dir = (PE_(image_import_directory)*)realloc (import_dir, ((1 + indx) * dir_size));
			if (!new_import_dir) {
				r_sys_perror ("malloc (import directory)");
				free (import_dir);
				import_dir = NULL;
				break; //
			}
			import_dir = new_import_dir;
			new_import_dir = NULL;
			curr_import_dir = import_dir + (indx - 1);
			if (r_buf_read_at (bin->b, import_dir_offset + (indx - 1) * dir_size, (ut8*) (curr_import_dir), dir_size) < 1) {
				bprintf ("Warning: read (import directory)\n");
				free (import_dir);
				import_dir = NULL;
				break; //return false;
			}
			count++;
		} while (curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
		curr_import_dir->TimeDateStamp != 0 || curr_import_dir->Characteristics != 0 ||
		curr_import_dir->ForwarderChain != 0);

		bin->import_directory = import_dir;
		bin->import_directory_size = import_dir_size;
	}

	indx = 0;
	if (bin->b->length > 0) {
		if ((delay_import_dir_offset != 0) && (delay_import_dir_offset < (ut32) bin->b->length)) {
			ut64 off;
			bin->delay_import_directory_offset = delay_import_dir_offset;
			do {
				indx++;
				off = indx * delay_import_size;
				if (off >= bin->b->length) {
					bprintf ("Warning: Cannot find end of import symbols\n");
					break;
				}
				delay_import_dir = (PE_(image_delay_import_directory)*)realloc (
					delay_import_dir, (indx * delay_import_size) + 1);
				if (delay_import_dir == 0) {
					r_sys_perror ("malloc (delay import directory)");
					free (delay_import_dir);
					return false;
				}

				curr_delay_import_dir = delay_import_dir + (indx - 1);
				rr = r_buf_read_at (bin->b, delay_import_dir_offset + (indx - 1) * delay_import_size,
					(ut8*) (curr_delay_import_dir), dir_size);
				if (rr != dir_size) {
					bprintf ("Warning: read (delay import directory)\n");
					goto fail;
				}
			} while (curr_delay_import_dir->Name != 0);
			bin->delay_import_directory = delay_import_dir;
		}
	}

	return true;
fail:
	free (import_dir);
	import_dir = NULL;
	bin->import_directory = import_dir;
	free (delay_import_dir);
	return false;
}

Project: radare2
File: pe.c

static int bin_pe_init_tls(struct PE_(r_bin_pe_obj_t)* bin) {
	PE_(image_tls_directory) * image_tls_directory;
	PE_(image_data_directory) * data_dir_tls = &bin->data_directory[PE_IMAGE_DIRECTORY_ENTRY_TLS];
	PE_DWord tls_paddr = bin_pe_rva_to_paddr (bin, data_dir_tls->VirtualAddress);

	image_tls_directory = R_NEW0 (PE_(image_tls_directory));
	if (r_buf_read_at (bin->b, tls_paddr, (ut8*) image_tls_directory, sizeof (PE_(image_tls_directory))) != sizeof (PE_(image_tls_directory))) {
		bprintf ("Warning: read (image_tls_directory)\n");
		free (image_tls_directory);
		return 0;
	}
	bin->tls_directory = image_tls_directory;
	if (!image_tls_directory->AddressOfCallBacks) {
		return 0;
	}
	if (image_tls_directory->EndAddressOfRawData < image_tls_directory->StartAddressOfRawData) {
		return 0;
	}
	PE_DWord callbacks_paddr = bin_pe_rva_to_paddr (bin, bin_pe_va_to_rva (bin,
			(PE_DWord) image_tls_directory->AddressOfCallBacks));
	bin_pe_store_tls_callbacks (bin, callbacks_paddr);
	return 0;
}

Project: radare2

static int bin_pe_parse_imports(struct PE_(r_bin_pe_obj_t)* bin,
                                struct r_bin_pe_import_t** importp, int* nimp,
                                const char* dll_name,
                                PE_DWord OriginalFirstThunk,
                                PE_DWord FirstThunk) {
	char import_name[PE_NAME_LENGTH + 1];
	char name[PE_NAME_LENGTH + 1];
	PE_Word import_hint, import_ordinal = 0;
	PE_DWord import_table = 0, off = 0;
	int i = 0, len;
	Sdb* db = NULL;
	char* sdb_module = NULL;
	char* symname;
	char* filename;
	char* symdllname = NULL;

	if (!dll_name || *dll_name == '0') {
		return 0;
	}

	if (!(off = bin_pe_rva_to_paddr (bin, OriginalFirstThunk)) &&
	!(off = bin_pe_rva_to_paddr (bin, FirstThunk))) {
		return 0;
	}
	do {
		if (import_ordinal >= UT16_MAX) {
			break;
		}
		if (off + i * sizeof(PE_DWord) > bin->size) {
			break;
		}
		len = r_buf_read_at (bin->b, off + i * sizeof (PE_DWord), (ut8*) &import_table, sizeof (PE_DWord));
		if (len != sizeof (PE_DWord)) {
			bprintf ("Warning: read (import table)\n");
			goto error;
		} else if (import_table) {
			if (import_table & ILT_MASK1) {
				import_ordinal = import_table & ILT_MASK2;
				import_hint = 0;
				snprintf (import_name, PE_NAME_LENGTH, "%s_Ordinal_%i", dll_name, import_ordinal);
				free (symdllname);
				strncpy (name, dll_name, sizeof (name) - 1);
				name[sizeof(name) - 1] = 0;
				symdllname = strdup (name);

				size_t len = strlen (symdllname);
				r_str_case (symdllname, 0);
				len = len < 4? 0: len - 4;
				symdllname[len] = 0;

				if (!sdb_module || strcmp (symdllname, sdb_module)) {
					sdb_free (db);
					if (db) {
						sdb_free (db);
					}
					db = NULL;
					free (sdb_module);
					sdb_module = strdup (symdllname);
					filename = sdb_fmt ("%s.sdb", symdllname);
					if (r_file_exists (filename)) {
						db = sdb_new (NULL, filename, 0);
					} else {
#if __WINDOWS__
						char invoke_dir[MAX_PATH];
						if (r_sys_get_src_dir_w32 (invoke_dir)) {
							filename = sdb_fmt ("%s\\share\\radare2\\"R2_VERSION "\\format\\dll\\%s.sdb", invoke_dir, symdllname);
						} else {
							filename = sdb_fmt ("share/radare2/"R2_VERSION "/format/dll/%s.sdb", symdllname);
						}
#else
						const char *dirPrefix = r_sys_prefix (NULL);
						filename = sdb_fmt ("%s/share/radare2/" R2_VERSION "/format/dll/%s.sdb", dirPrefix, symdllname);
#endif
						if (r_file_exists (filename)) {
							db = sdb_new (NULL, filename, 0);
						}
					}
				}
				if (db) {
					symname = resolveModuleOrdinal (db, symdllname, import_ordinal);
					if (symname) {
						snprintf (import_name, PE_NAME_LENGTH, "%s_%s", dll_name, symname);
						R_FREE (symname);
					}
				} else {
					bprintf ("Cannot find %s\n", filename);

				}
			} else {
				import_ordinal++;
				const ut64 off = bin_pe_rva_to_paddr (bin, import_table);
				if (off > bin->size || (off + sizeof (PE_Word)) > bin->size) {
					bprintf ("Warning: off > bin->size\n");
					goto error;
				}
				len = r_buf_read_at (bin->b, off, (ut8*) &import_hint, sizeof (PE_Word));
				if (len != sizeof (PE_Word)) {
					bprintf ("Warning: read import hint at 0x%08"PFMT64x "\n", off);
					goto error;
				}
				name[0] = '\0';
				len = r_buf_read_at (bin->b, off + sizeof(PE_Word), (ut8*) name, PE_NAME_LENGTH);
				if (len < 1) {
					bprintf ("Warning: read (import name)\n");
					goto error;
				} else if (!*name) {
					break;
				}
				name[PE_NAME_LENGTH] = '\0';
				snprintf (import_name, PE_NAME_LENGTH, "%s_%s", dll_name, name);
			}
			if (!(*importp = realloc (*importp, (*nimp + 1) * sizeof(struct r_bin_pe_import_t)))) {
				r_sys_perror ("realloc (import)");
				goto error;
			}
			memcpy ((*importp)[*nimp].name, import_name, PE_NAME_LENGTH);
			(*importp)[*nimp].name[PE_NAME_LENGTH] = '\0';
			(*importp)[*nimp].vaddr = bin_pe_rva_to_va (bin, FirstThunk + i * sizeof (PE_DWord));
			(*importp)[*nimp].paddr = bin_pe_rva_to_paddr (bin, FirstThunk) + i * sizeof(PE_DWord);
			(*importp)[*nimp].hint = import_hint;
			(*importp)[*nimp].ordinal = import_ordinal;
			(*importp)[*nimp].last = 0;
			(*nimp)++;
			i++;
		}
	} while (import_table);

	if (db) {
		sdb_free (db);
		db = NULL;
	}
	free (symdllname);
	free (sdb_module);
	return i;

error:
	if (db) {
		sdb_free (db);
		db = NULL;
	}
	free (symdllname);
	free (sdb_module);
	return false;
}

Project: radare2
File: pe.c

static PE_DWord bin_pe_rva_to_paddr(RBinPEObj* bin, PE_DWord rva) {
	PE_DWord section_base;
	int i, section_size;
	for (i = 0; i < bin->num_sections; i++) {
		section_base = bin->section_header[i].VirtualAddress;
		section_size = bin->section_header[i].Misc.VirtualSize;
		if (rva >= section_base && rva < section_base + section_size) {
			return bin->section_header[i].PointerToRawData + (rva - section_base);
		}
	}
	return rva;
}

Project: radare2

struct r_bin_pe_addr_t *PE_(check_msvcseh) (struct PE_(r_bin_pe_obj_t) *bin) {
	struct r_bin_pe_addr_t* entry;
	ut8 b[512];
	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] == 0xe8 && b[5] == 0xe9) {
		const st32 jmp_dst = r_read_ble32 (b + 6, bin->big_endian);
		entry->paddr += (5 + 5 + jmp_dst);
		entry->vaddr += (5 + 5 + jmp_dst);
		if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) > 0) {
			ut32 imageBase = bin->nt_headers->optional_header.ImageBase;
			for (n = 0; n < sizeof (b) - 6; n++) {
				const ut32 tmp_imgbase = r_read_ble32 (b + n + 1, bin->big_endian);
				if (b[n] == 0x68 && tmp_imgbase == imageBase && b[n + 5] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 6, bin->big_endian);
					entry->paddr += (n + 5 + 5 + call_dst);
					entry->vaddr += (n + 5 + 5 + call_dst);
					return entry;
				}
			}
			for (n = 0; n < sizeof (b) - 6; n++) {
				if (b[n] == 0x50 && b[n+1] == 0xff && b[n + 3] == 0xff && b[n + 5] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 6, bin->big_endian);
					entry->paddr += (n + 5 + 5 + call_dst);
					entry->vaddr += (n + 5 + 5 + call_dst);
					return entry;
				}
			}
			for (n = 0; n < sizeof (b) - 20; n++) {
				if (b[n] == 0x50 && b[n + 1] == 0xff && b[n + 7] == 0xff && b[n + 13] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 14, bin->big_endian);
					entry->paddr += (n + 5 + 13 + call_dst);
					entry->vaddr += (n + 5 + 13 + call_dst);
					return entry;
				}
			}
			for (n = 0; n < sizeof (b) - 5; n++) {
				if (b[n] == 0x50 && b[n + 1] == 0x57 && b[n + 2] == 0xff && b[n + 4] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 5, bin->big_endian);
					entry->paddr += (n + 5 + 4 + call_dst);
					entry->vaddr += (n + 5 + 4 + call_dst);
					return entry;
				}
			}

		}
	}
	if (b[4] == 0xe8 && b[13] == 0xe9) {
		const st32 jmp_dst = r_read_ble32 (b + 14, bin->big_endian);
		entry->paddr += (5 + 13 + jmp_dst);
		entry->vaddr += (5 + 13 + jmp_dst);
		if (r_buf_read_at (bin->b, entry->paddr, b, sizeof (b)) > 0) {
			for (n = 0; n < sizeof (b) - 13; n++) {
				if (b[n] == 0x4c && b[n + 3] == 0x48 && b[n + 6] == 0x8b && b[n + 8] == 0xe8) {
					const st32 call_dst = r_read_ble32 (b + n + 9, bin->big_endian);
					entry->paddr += (n + 5 + 8 + call_dst);
					entry->vaddr += (n + 5 + 8 + call_dst);
					return entry;
				}
			}
		}
	}
	if (b[188] == 0x50 && b[201] == 0xe8) {
		const st32 call_dst = r_read_ble32 (b + 202, bin->big_endian);
		entry->paddr += (201 + 5 + call_dst);
		entry->vaddr += (201 + 5 + call_dst);
		return entry;
	}

	if (b[292] == 0x50 && b[303] == 0xe8) {
		const st32 call_dst = r_read_ble32 (b + 304, bin->big_endian);
		entry->paddr += (303 + 5 + call_dst);
		entry->vaddr += (303 + 5 + call_dst);
		return entry;
	}

	free (entry);
	return NULL;
}

Project: radare2
File: pe.c

static void free_Var(Var* var) {
	if (var) {
		free (var->szKey);
		free (var->Value);
		free (var);
	}
}