⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pe_linker.c

📁 linux下安装无线网卡启动的程式
💻 C
📖 第 1 页 / 共 2 页
字号:
	int ret = 0;	IMAGE_IMPORT_DESCRIPTOR *dirent;	IMAGE_DATA_DIRECTORY *import_data_dir;	PIMAGE_OPTIONAL_HEADER opt_hdr;	opt_hdr = &nt_hdr->OptionalHeader;	import_data_dir =		&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];	dirent = RVA2VA(image, import_data_dir->VirtualAddress,			IMAGE_IMPORT_DESCRIPTOR *);	for (i = 0; dirent[i].Name; i++) {		name = RVA2VA(image, dirent[i].Name, char*);		DBGLINKER("imports from dll: %s", name);		ret += import(image, &dirent[i], name);	}	return ret;}static int fixup_reloc(void *image, IMAGE_NT_HEADERS *nt_hdr){	ULONG_PTR base;	ULONG_PTR size;	IMAGE_BASE_RELOCATION *fixup_block;	IMAGE_DATA_DIRECTORY *base_reloc_data_dir;	PIMAGE_OPTIONAL_HEADER opt_hdr;	opt_hdr = &nt_hdr->OptionalHeader;	base = opt_hdr->ImageBase;	base_reloc_data_dir =		&opt_hdr->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];	if (base_reloc_data_dir->Size == 0)		return 0;	fixup_block = RVA2VA(image, base_reloc_data_dir->VirtualAddress,			     IMAGE_BASE_RELOCATION *);	DBGLINKER("fixup_block=%p, image=%p", fixup_block, image);	DBGLINKER("fixup_block info: %x %d",		  fixup_block->VirtualAddress, fixup_block->SizeOfBlock);	while (fixup_block->SizeOfBlock) {		int i;		WORD fixup, offset;		size = (fixup_block->SizeOfBlock -			sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);		DBGLINKER("found %Lu relocations in this block",			  (uint64_t)size);		for (i = 0; i < size; i++) {			fixup = fixup_block->TypeOffset[i];			offset = fixup & 0xfff;			switch ((fixup >> 12) & 0x0f) {			case IMAGE_REL_BASED_ABSOLUTE:				break;			case IMAGE_REL_BASED_HIGHLOW: {				uint32_t addr;				uint32_t *loc =					RVA2VA(image,					       fixup_block->VirtualAddress +					       offset, uint32_t *);				addr = RVA2VA(image, (*loc - base), uint32_t);				DBGLINKER("relocation: *%p (Val:%X)= %X",					  loc, *loc, addr);				*loc = addr;			}				break;			case IMAGE_REL_BASED_DIR64: {				uint64_t addr;				uint64_t *loc =					RVA2VA(image,					       fixup_block->VirtualAddress +					       offset, uint64_t *);				addr = RVA2VA(image, (*loc - base), uint64_t);				DBGLINKER("relocation: *%p (Val:%llX)= %llx",					  loc, *loc, addr);				*loc = addr;			}				break;			default:				ERROR("unknown fixup: %08X",				      (fixup >> 12) & 0x0f);				return -EOPNOTSUPP;				break;			}		}		DBGLINKER("finished relocating block");		fixup_block = (IMAGE_BASE_RELOCATION *)			((void *)fixup_block + fixup_block->SizeOfBlock);	};	DBGLINKER("done relocating all");	return 0;}/* Expand the image in memroy if necessary. The image on disk does not * necessarily maps the image of the driver in memory, so we have to * re-write it in order to fullfill the sections alignements. The * advantage to do that is that rva_to_va becomes a simple * addition. */static int fix_pe_image(struct pe_image *pe){	void *image;	IMAGE_SECTION_HEADER *sect_hdr;	int i, sections;	int image_size;	if (pe->size == pe->opt_hdr->SizeOfImage) {		/* Nothing to do */		return 0;	}	image_size = pe->opt_hdr->SizeOfImage;#ifdef CONFIG_X86_64#ifdef PAGE_KERNEL_EXECUTABLE	image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,			  PAGE_KERNEL_EXECUTABLE);#elif defined PAGE_KERNEL_EXEC	image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,			  PAGE_KERNEL_EXEC);#else#error x86_64 should have either PAGE_KERNEL_EXECUTABLE or PAGE_KERNEL_EXEC#endif#else#ifdef cpu_has_nx	/* hate to play with kernel macros, but PAGE_KERNEL_EXEC is	 * not available to modules! */	if (cpu_has_nx)		image = __vmalloc(image_size, GFP_KERNEL | __GFP_HIGHMEM,				  __pgprot(__PAGE_KERNEL & ~_PAGE_NX));	else		image = vmalloc(image_size);#else		image = vmalloc(image_size);#endif#endif	if (image == NULL) {		ERROR("failed to allocate enough space for new image:"		      " %d bytes", image_size);		return -ENOMEM;	}	/* Copy all the headers, ie everything before the first section. */	sections = pe->nt_hdr->FileHeader.NumberOfSections;	sect_hdr = IMAGE_FIRST_SECTION(pe->nt_hdr);	DBGLINKER("copying headers: %u bytes", sect_hdr->PointerToRawData);	memcpy(image, pe->image, sect_hdr->PointerToRawData);	/* Copy all the sections */	for (i = 0; i < sections; i++) {		DBGLINKER("Copy section %s from %x to %x",			  sect_hdr->Name, sect_hdr->PointerToRawData,			  sect_hdr->VirtualAddress);		if (sect_hdr->VirtualAddress+sect_hdr->SizeOfRawData >		    image_size) {			ERROR("Invalid section %s in driver", sect_hdr->Name);			vfree(image);			return -EINVAL;		}		memcpy(image+sect_hdr->VirtualAddress,		       pe->image + sect_hdr->PointerToRawData,		       sect_hdr->SizeOfRawData);		sect_hdr++;	}	vfree(pe->image);	pe->image = image;	pe->size = image_size;	/* Update our internal pointers */	pe->nt_hdr = (IMAGE_NT_HEADERS *)		(pe->image + ((IMAGE_DOS_HEADER *)pe->image)->e_lfanew);	pe->opt_hdr = &pe->nt_hdr->OptionalHeader;	DBGLINKER("set nt headers: nt_hdr=%p, opt_hdr=%p, image=%p",		  pe->nt_hdr, pe->opt_hdr, pe->image);	return 0;}#if defined(CONFIG_X86_64)extern struct kuser_shared_data kuser_shared_data;void fix_user_shared_data_addr(char *driver, unsigned long length){	unsigned long i, n, max_addr, *addr;	n = length - sizeof(unsigned long);	max_addr = KI_USER_SHARED_DATA + sizeof(kuser_shared_data);	for (i = 0; i < n; i++) {		addr = (unsigned long *)(driver + i);		if (*addr >= KI_USER_SHARED_DATA && *addr < max_addr) {			*addr -= KI_USER_SHARED_DATA;			*addr += (unsigned long)&kuser_shared_data;			kuser_shared_data.reserved1 = 1;		}	}}#endifint link_pe_images(struct pe_image *pe_image, unsigned short n){	int i;	struct pe_image *pe;#ifdef DEBUG	/* Sanity checkings */	CHECK_SZ(IMAGE_SECTION_HEADER, IMAGE_SIZEOF_SECTION_HEADER);	CHECK_SZ(IMAGE_FILE_HEADER, IMAGE_SIZEOF_FILE_HEADER);	CHECK_SZ(IMAGE_OPTIONAL_HEADER, IMAGE_SIZEOF_NT_OPTIONAL_HEADER);	CHECK_SZ(IMAGE_NT_HEADERS, 4 + IMAGE_SIZEOF_FILE_HEADER +		 IMAGE_SIZEOF_NT_OPTIONAL_HEADER);	CHECK_SZ(IMAGE_DOS_HEADER, 0x40);	CHECK_SZ(IMAGE_EXPORT_DIRECTORY, 40);	CHECK_SZ(IMAGE_BASE_RELOCATION, 8);	CHECK_SZ(IMAGE_IMPORT_DESCRIPTOR, 20);#endif	for (i = 0; i < n; i++) {		IMAGE_DOS_HEADER *dos_hdr;		pe = &pe_image[i];		dos_hdr = pe->image;		if (pe->size < sizeof(IMAGE_DOS_HEADER)) {			TRACE1("image too small: %d", pe->size);			return -EINVAL;		}		pe->nt_hdr =			(IMAGE_NT_HEADERS *)(pe->image + dos_hdr->e_lfanew);		pe->opt_hdr = &pe->nt_hdr->OptionalHeader;		pe->type = check_nt_hdr(pe->nt_hdr);		if (pe->type <= 0) {			TRACE1("type <= 0");			return -EINVAL;		}		if (fix_pe_image(pe)) {			TRACE1("bad PE image");			return -EINVAL;		}		if (read_exports(pe)) {			TRACE1("read exports failed");			return -EINVAL;		}	}	for (i = 0; i < n; i++) {	        pe = &pe_image[i];		if (fixup_reloc(pe->image, pe->nt_hdr)) {			TRACE1("fixup reloc failed");			return -EINVAL;		}		if (fixup_imports(pe->image, pe->nt_hdr)) {			TRACE1("fixup imports failed");			return -EINVAL;		}#if defined(CONFIG_X86_64)		INFO("fixing KI_USER_SHARED_DATA address in the driver");		fix_user_shared_data_addr(pe_image[i].image, pe_image[i].size);#endif		flush_icache_range(pe->image, pe->size);		pe->entry =			RVA2VA(pe->image,			       pe->opt_hdr->AddressOfEntryPoint, void *);		TRACE1("entry is at %p, rva at %08X", pe->entry,		       pe->opt_hdr->AddressOfEntryPoint);	}	for (i = 0; i < n; i++) {	        pe = &pe_image[i];		if (pe->type == IMAGE_FILE_DLL) {			struct unicode_string ustring;			char *buf = "0/0t0m0p00";			int (*dll_entry)(struct unicode_string *ustring)				wstdcall;			memset(&ustring, 0, sizeof(ustring));			ustring.buf = (wchar_t *)buf;			dll_entry = (void *)get_dll_init(pe->name);			TRACE1("calling dll_init at %p", dll_entry);			if (!dll_entry || dll_entry(&ustring))				ERROR("DLL initialize failed for %s",				      pe->name);		}		else if (pe->type != IMAGE_FILE_EXECUTABLE_IMAGE)			ERROR("illegal image type: %d", pe->type);	}	return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -