コード例 #1
0
ファイル: imports.cpp プロジェクト: JusticeRage/Manalyze
bool PE::_parse_delayed_imports()
{
    if (!_ioh || _file_handle == nullptr) { // Image Optional Header wasn't parsed successfully.
        return false;
    }
    if (!_reach_directory(IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT))	{ // No delayed imports
        return true;
    }

    delay_load_directory_table dldt;
	memset(&dldt, 0, 8*sizeof(boost::uint32_t));
    if (1 != fread(&dldt, 8*sizeof(boost::uint32_t), 1, _file_handle.get()))
    {
        PRINT_WARNING << "Could not read the Delay-Load Directory Table!" << std::endl;
        return true;
    }

    unsigned int offset = _rva_to_offset(dldt.Name);
    if (offset == 0)
    {
        PRINT_WARNING << "Could not read the name of the DLL to be delay-loaded!" << std::endl;
        return true;
    }

	// Read the delayed DLL's name
    std::string name;
    utils::read_string_at_offset(_file_handle.get(), offset, name);
	pImportedLibrary library(new ImportedLibrary(name));

	dldt.NameStr = name;
	_delay_load_directory_table.reset(dldt);

	// Read the imports
	offset = _rva_to_offset(dldt.DelayImportNameTable);

	if (_parse_import_lookup_table(offset, library)) {
		_imports.push_back(library);
	}
	return true;
}
コード例 #2
0
ファイル: imports.cpp プロジェクト: JusticeRage/Manalyze
bool PE::_parse_imports()
{
	if (!_ioh || _file_handle == nullptr) { // Image Optional Header wasn't parsed successfully.
		return false;
	}
	if (!_reach_directory(IMAGE_DIRECTORY_ENTRY_IMPORT))	{ // No imports
		return true;
	}

	while (true) // We stop at the first NULL IMAGE_IMPORT_DESCRIPTOR.
	{
		pimage_import_descriptor iid(new image_import_descriptor);
		memset(iid.get(), 0, 5*sizeof(boost::uint32_t)); // Don't overwrite the last member (a string)

		if (20 != fread(iid.get(), 1, 20, _file_handle.get()))
		{
			PRINT_ERROR << "Could not read the IMAGE_IMPORT_DESCRIPTOR." << std::endl;
			return true; // Don't give up on the rest of the parsing.
		}

		// Exit condition
		if (iid->OriginalFirstThunk == 0 && iid->FirstThunk == 0) {
			break;
		}

		// Non-standard parsing. The Name RVA is translated to an actual string here.
		auto offset = _rva_to_offset(iid->Name);
		if (!offset) { // Try to use the RVA as a direct address if the imports are outside of a section.
			offset = iid->Name;
		}
		std::string library_name;
		if (!utils::read_string_at_offset(_file_handle.get(), offset, library_name))
		{
			// It seems that the Windows loader doesn't give up if such a thing happens.
			if (_imports.size() > 0)
			{
				PRINT_WARNING << "Could not read an import's name." << std::endl;
				break; // Try to continue the parsing with the available imports.
			}

			PRINT_ERROR << "Could not read an import's name." << std::endl;
			return true;
		}

		pImportedLibrary library = pImportedLibrary(new ImportedLibrary(library_name, iid));
		_imports.push_back(library);
	}

	// Parse the IMPORT_LOOKUP_TABLE for each imported library
	for (auto it = _imports.begin() ; it != _imports.end() ; ++it)
	{
		int ilt_offset;
		auto descriptor = (*it)->get_image_import_descriptor();
		if (descriptor == nullptr)
		{
			// Should never happen, standard (as opposed to delay-loaded) imports all have image import descriptors.
			PRINT_WARNING << "Tried to parse imported functions, but no image import descriptor was given!" << DEBUG_INFO_INSIDEPE << std::endl;
			continue;
		}

		if (descriptor->OriginalFirstThunk != 0) {
			ilt_offset = _rva_to_offset(descriptor->OriginalFirstThunk);
		}
		else { // Some packed executables use FirstThunk and set OriginalFirstThunk to 0.
			ilt_offset = _rva_to_offset(descriptor->FirstThunk);
		}

		if (!_parse_import_lookup_table(ilt_offset, *it))
		{
			// Non fatal. Stop trying to parse imports, but the ones already read will still be available.
			if ((*it)->get_name() != nullptr) {
				PRINT_WARNING << "An error occurred while trying to read functions imported by " << *(*it)->get_name()
							  << "." << DEBUG_INFO_INSIDEPE << std::endl;
			}
			return true;
		}
	}

	return true;
}
コード例 #3
0
ファイル: imports.cpp プロジェクト: melbcat/Manalyze
bool PE::_parse_imports(FILE* f)
{
	if (!_ioh) { // Image Optional Header wasn't parsed successfully.
		return false;
	}
	if (!_reach_directory(f, IMAGE_DIRECTORY_ENTRY_IMPORT))	{ // No imports
		return true;
	}

	while (true) // We stop at the first NULL IMAGE_IMPORT_DESCRIPTOR.
	{
		pimage_import_descriptor iid(new image_import_descriptor);
		memset(iid.get(), 0, 5*sizeof(boost::uint32_t)); // Don't overwrite the last member (a string)

		if (20 != fread(iid.get(), 1, 20, f))
		{
			PRINT_ERROR << "Could not read the IMAGE_IMPORT_DESCRIPTOR." << std::endl;
			return true; // Don't give up on the rest of the parsing.
		}

		// Exit condition
		if (iid->OriginalFirstThunk == 0 && iid->FirstThunk == 0) {
			break;
		}

		// Non-standard parsing. The Name RVA is translated to an actual string here.
		auto offset = _rva_to_offset(iid->Name);
		if (!offset) { // Try to use the RVA as a direct address if the imports are outside of a section.
			offset = iid->Name;
		}
		if (!utils::read_string_at_offset(f, offset, iid->NameStr))
		{
			// It seems that the Windows loader doesn't give up if such a thing happens.
			if (_imports.size() > 0)
			{
				PRINT_WARNING << "Could not read an import's name." << std::endl;
				break; // Try to continue the parsing with the available imports.
			}

			PRINT_ERROR << "Could not read an import's name." << std::endl;
			return true;
		}

		pimage_library_descriptor library = boost::make_shared<image_library_descriptor>(iid, std::vector<pimport_lookup_table>());
		_imports.push_back(library);
	}

	// Parse the IMPORT_LOOKUP_TABLE for each imported library
	for (auto it = _imports.begin() ; it != _imports.end() ; ++it)
	{
		int ilt_offset;
		if ((*it)->first->OriginalFirstThunk != 0) {
			ilt_offset = _rva_to_offset((*it)->first->OriginalFirstThunk);
		}
		else { // Some packed executables use FirstThunk and set OriginalFirstThunk to 0.
			ilt_offset = _rva_to_offset((*it)->first->FirstThunk);
		}
		if (!ilt_offset || fseek(f, ilt_offset, SEEK_SET))
		{
			PRINT_ERROR << "Could not reach an IMPORT_LOOKUP_TABLE." << std::endl;
			return true;
		}

		while (true) // We stop at the first NULL IMPORT_LOOKUP_TABLE
		{
			pimport_lookup_table import = boost::make_shared<import_lookup_table>();
			import->AddressOfData = 0;
			import->Hint = 0;

			// The field has a size of 8 for x64 PEs
			int size_to_read = (_ioh->Magic == nt::IMAGE_OPTIONAL_HEADER_MAGIC.at("PE32+") ? 8 : 4);
			if (size_to_read != fread(&(import->AddressOfData), 1, size_to_read, f))
			{
				PRINT_ERROR << "Could not read the IMPORT_LOOKUP_TABLE." << std::endl;
				return true;
			}

			// Exit condition
			if (import->AddressOfData == 0) {
				break;
			}

			// Read the HINT/NAME TABLE if applicable. Check the most significant byte of AddressOfData to
			// see if the import is by name or ordinal. For PE32+, AddressOfData is a uint64.
			boost::uint64_t mask = (size_to_read == 8 ? 0x8000000000000000 : 0x80000000);
			if (!(import->AddressOfData & mask))
			{
				// Import by name. Read the HINT/NAME table. For both PE32 and PE32+, its RVA is stored
				// in bits 30-0 of AddressOfData.
				unsigned int table_offset = _rva_to_offset(import->AddressOfData & 0x7FFFFFFF);
				if (table_offset == 0)
				{
					PRINT_ERROR << "Could not reach the HINT/NAME table." << std::endl;
					return true;
				}

				unsigned int saved_offset = ftell(f);
				if (saved_offset == -1 || fseek(f, table_offset, SEEK_SET) || 2 != fread(&(import->Hint), 1, 2, f))
				{
					PRINT_ERROR << "Could not read a HINT/NAME hint." << std::endl;
					return true;
				}
				import->Name = utils::read_ascii_string(f);

				//TODO: Demangle the import name

				// Go back to the import lookup table.
				if (fseek(f, saved_offset, SEEK_SET)) {
					return true;
				}
			}

			(*it)->second.push_back(import);
		}
	}

	return true;
}