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

📄 binfmt_pe.c

📁 该项目主要是将wingdows程序直接运行在linux上
💻 C
📖 第 1 页 / 共 2 页
字号:
} /* end pe_map *//* originally by binfmt_elf.c */static unsigned long randomize_stack_top(unsigned long stack_top){	unsigned int random_variable = 0;	if (current->flags & PF_RANDOMIZE)		random_variable = get_random_int() % (8*1024*1024);#ifdef CONFIG_STACK_GROWSUP	return PAGE_ALIGN(stack_top + random_variable);#else	return PAGE_ALIGN(stack_top - random_variable);#endif}/* * load_pe_binary */static int load_pe_binary(struct linux_binprm *bprm, struct pt_regs *regs){	IMAGE_DOS_HEADER	*dos_hdr;	struct win32_section	*ws = NULL;	struct win32_image_section	*wis;	unsigned long error;	int retval = 0;	unsigned long pe_entry, ntdll_load_addr = 0;	unsigned long start_code, end_code, start_data, end_data;	unsigned long reloc_func_desc = 0;	unsigned long ntdll_entry;	struct files_struct *files;	int executable_stack = EXSTACK_DEFAULT;	unsigned long def_flags = 0;	unsigned long stack_top;	unsigned long ret_addr = 0xdeadbeef;	unsigned long start_address;	unsigned long pe_brk = 0;#ifdef NTDLL_SO	char		*ntdll_name;	unsigned long	interp_load_addr;	unsigned long	interp_entry;#endif	int		maped = 0;	struct win32_object	*proc_obj, *thread_obj;	struct eprocess	*process;	struct ethread	*thread;	struct ethread_cons_data	etcd;	PRTL_USER_PROCESS_PARAMETERS	ppb;	PKAPC	thread_apc;	/* check the DOS header */	retval = -ENOEXEC;	dos_hdr = (IMAGE_DOS_HEADER *)bprm->buf;	if (dos_hdr->e_magic != IMAGE_DOS_SIGNATURE || dos_hdr->e_lfanew <= 0)		goto out;	retval = -ENOMEM;	ws = (struct win32_section *)kmalloc(sizeof(struct win32_section), GFP_KERNEL);	if (!ws)		goto out;	memset(ws, 0, sizeof(*ws));	files = current->files;		/* Refcounted so ok */	retval = unshare_files();	if (retval < 0) {		kfree(ws);		goto out;	}	if (files == current->files) {		put_files_struct(files);		files = NULL;	}	start_code = ~0UL;	end_code = 0;	start_data = 0;	end_data = 0;	/* Flush all traces of the currently running executable */	retval = flush_old_exec(bprm);	if (retval) {		kfree(ws);		goto out;	}	/* Discard our unneeded old files struct */	if (files) {		steal_locks(files);		put_files_struct(files);		files = NULL;	}	/* OK, This is the point of no return */	current->mm->start_data = 0;	current->mm->end_data = 0;	current->mm->end_code = 0;	current->mm->mmap = NULL;	current->flags &= ~PF_FORKNOEXEC;	current->mm->def_flags = def_flags;	if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)		current->flags |= PF_RANDOMIZE;	arch_pick_mmap_layout(current->mm);	/* Do this so that we can load the ntdll, if need be.  We will	   change some of these later */	set_mm_counter(current->mm, rss, 0);	current->mm->free_area_cache = current->mm->mmap_base;	current->mm->cached_hole_size = 0;	retval = setup_arg_pages(bprm, stack_top = randomize_stack_top(STACK_TOP),				 executable_stack);	if (retval < 0)		goto out_free_file;	current->mm->start_stack = bprm->p;	/* map PE image */	ws->ws_file = bprm->file;	image_section_setup(ws);	pe_map(ws, 0);	maped = 1;	/* Now we do a little grungy work by mmaping the PE image into	   the correct location in memory.  At this point, we assume that	   the image should be loaded at fixed address, not at a variable	   address. */	for (wis = ws->ws_sections; wis < ws->ws_sections + ws->ws_nsecs; wis++) {		unsigned long k;		if (wis->wis_character & IMAGE_SCN_TYPE_NOLOAD)			continue;		k = ws->ws_realbase + wis->wis_rva;		/*		 * Check to see if the section's size will overflow the		 * allowed task size. Note that p_filesz must always be		 * <= p_memsz so it is only necessary to check p_memsz.		 */		if (k > TASK_SIZE || TASK_SIZE - wis->wis_size < k) /* Avoid overflows.  */			goto out_free_file;		if (wis->wis_character & IMAGE_SCN_MEM_EXECUTE) {			start_code = k;			end_code = k + wis->wis_rawsize;		}		else {			if (!start_data)				start_data = k;			end_data = k + wis->wis_rawsize;		}		k += wis->wis_size;		if (pe_brk < k)	/* pe_brk used set mm->brk */			pe_brk = k;		/* TODO: start_data and end_data, diff to ELF */	}	current->mm->brk = pe_brk;	/* extra page, used for interpreter ld-linux.so */	down_write(&current->mm->mmap_sem);	if ((extra_page = do_brk(pe_brk, PAGE_SIZE)) != pe_brk) {		up_write(&current->mm->mmap_sem);		goto out_free_file;	}	up_write(&current->mm->mmap_sem);	current->mm->brk = pe_brk + PAGE_SIZE;	ws->ws_entrypoint += ws->ws_realbase;#ifdef NTDLL_SO	/* search ntdll.dll.so in $PATH, default is /usr/local/lib/wine/ntdll.dll.so */	ntdll_name = search_ntdll(bprm);	/* map ntdll.dll.so */	LdrpMapSystemDll(current, ntdll_name, &ntdll_load_addr, &interp_load_addr);	pe_entry = get_pe_entry();	ntdll_entry = get_ntdll_entry();	interp_entry = get_interp_entry();#endif	reloc_func_desc = 0;	set_binfmt(&pe_format);	/* Create EPROCESS */	proc_obj = AllocObject(&process_objclass, NULL, NULL);	if (IS_ERR(proc_obj)) {		retval = PTR_ERR(proc_obj);		goto out_free_file;	}	process = proc_obj->o_private;	/* initialize EProcess and KProcess */	process->section_base_address = (void *)ws->ws_realbase;	/* FIXME: PsCreateCidHandle */	/* Create PEB */	if ((retval = create_peb(process)))		goto out_free_eproc;	/* Create PPB */	create_ppb(&ppb, process, bprm, bprm->filename, NULL, NULL, NULL, NULL, NULL, NULL, NULL);	((PEB *)process->peb)->ProcessParameters = ppb;#ifdef ARCH_HAS_SETUP_ADDITIONAL_PAGES	retval = arch_setup_additional_pages(bprm, executable_stack);	if (retval < 0) {		send_sig(SIGKILL, current, 0);		goto out;	}#endif /* ARCH_HAS_SETUP_ADDITIONAL_PAGES */	compute_creds(bprm);	current->flags &= ~PF_FORKNOEXEC;#ifdef NTDLL_SO	/* copy argv, env, and auxvec to stack, all for interpreter */	create_elf_tables(bprm, ntdll_load_addr, ntdll_phoff, ntdll_phnum, get_start_thunk());#endif	/* Set the Esp */#ifdef CONFIG_STACK_GROWSUP	;#else	/* setup user stack */	/* -------------    -----------	   param            PEB_BASE	   -------------    -----------	   start_address    entry point	   -------------    -----------	   ret_addr         0xdeadbeef	   -------------    -----------	   */	bprm->p = bprm->p			//stack_top		- sizeof(ret_addr)			// return address, BAD address		- sizeof(start_address)		// image entry point		- sizeof(unsigned long);	// paramters for entry point	current->mm->start_stack = bprm->p;	start_address = ws->ws_entrypoint;	*(unsigned long *)bprm->p = ret_addr;	*(unsigned long *)(bprm->p + sizeof(ret_addr)) = start_address;	*(unsigned long *)(bprm->p + sizeof(ret_addr) + sizeof(start_address)) = PEB_BASE;#endif	current->mm->end_code = end_code;	current->mm->start_code = start_code;	current->mm->start_data = start_data;	current->mm->end_data = end_data;	current->mm->start_stack = bprm->p;	if (current->personality & MMAP_PAGE_ZERO) {		/* Why this, you ask???  Well SVr4 maps page 0 as read-only,		   and some applications "depend" upon this behavior.		   Since we do not have the power to recompile these, we		   emulate the SVr4 behavior.  Sigh.  */		down_write(&current->mm->mmap_sem);		error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,				MAP_FIXED | MAP_PRIVATE, 0);		up_write(&current->mm->mmap_sem);	}	/* allocate a Win32 thread object */	etcd.etcd_task = current;	etcd.etcd_process = proc_obj;	etcd.etcd_stack_top = stack_top;	thread_obj = AllocObject(&thread_objclass, NULL, &etcd);	if (IS_ERR(thread_obj)) {		retval = PTR_ERR(thread_obj);		goto out_free_eproc;	}	/* the thread object can now be put, since a reference is held	 * by the Linux task structure. Similarly the process object	 * is now referenced by the thread object and can also be put	 */	objput(proc_obj);	objput(thread_obj);	thread = thread_obj->o_private;	/* set the teb */	thread->tcb.teb = create_teb(process, NULL, stack_top);	if (IS_ERR(thread->tcb.teb)) {		retval = PTR_ERR(thread->tcb.teb);		goto out_free_file;	}        	/* Init KThreaad */	KThreadInit(&thread->tcb, process);	set_teb_selector((long)thread->tcb.teb);	thread->start_address = (void *)pe_entry;	/* FIXME */	/* init apc, to call LdrInitializeThunk */	thread_apc = kmalloc(sizeof(KAPC), GFP_KERNEL);	if (!thread_apc) {		retval = -ENOMEM;		goto out_free_file;	}	KeInitializeApc(thread_apc,			&thread->tcb,			OriginalApcEnvironment,			PspThreadSpecialApc,			NULL,			(PKNORMAL_ROUTINE)ntdll_entry,			UserMode,			(void *)(bprm->p + 12));	KeInsertQueueApc(thread_apc, (void *)interp_entry, (void *)extra_page, IO_NO_INCREMENT);#ifndef TIF_APC#define	TIF_APC	13#endif	set_tsk_thread_flag(current, TIF_APC);#ifdef ELF_PLAT_INIT	/*	 * The ABI may specify that certain registers be set up in special	 * ways (on i386 %edx is the address of a DT_FINI function, for	 * example.  In addition, it may also specify (eg, PowerPC64 ELF)	 * that the e_entry field is the address of the function descriptor	 * for the startup routine, rather than the address of the startup	 * routine itself.  This macro performs whatever initialization to	 * the regs structure is required as well as any relocations to the	 * function descriptor entries when executing dynamically links apps.	 */	ELF_PLAT_INIT(regs, reloc_func_desc);#endif	start_thread(regs, pe_entry, bprm->p);	if (unlikely(current->ptrace & PT_PTRACED)) {		if (current->ptrace & PT_TRACE_EXEC)			ptrace_notify ((PTRACE_EVENT_EXEC << 8) | SIGTRAP);		else			send_sig(SIGTRAP, current, 0);	}	/* save current trap frame */	thread->tcb.trap_frame = (struct ktrap_frame *)regs;	retval = 0;	/* return from w32syscall_exit, not syscall_exit */	((unsigned long *)regs)[-1] = (unsigned long)w32syscall_exit;	asm volatile ("mov %0, %%fs\n" : : "r"(TEB_SELECTOR));out:	return retval;	/* error cleanup */out_free_eproc:	objput(proc_obj);	goto out_free_file;out_free_file:	if (files) {		put_files_struct(current->files);		current->files = files;	}	/* free win32_section, if not mapped */	if (!maped && ws) {		if (ws->ws_sections)			kfree(ws->ws_sections);		kfree(ws);	}	send_sig(SIGKILL, current, 0);	goto out;} /* end load_pe_binary *//* * PspThreadSpecialApc */voidSTDCALLPspThreadSpecialApc(PKAPC Apc,		PKNORMAL_ROUTINE* NormalRoutine,		PVOID* NormalContext,		PVOID* SystemArgument1,		PVOID* SystemArgument2){	ktrace("PspThreadSpecialApc\n");	kfree(Apc);} /* end PspThreadSpecialApc */int __init init_pe_binfmt(void){	return register_binfmt(&pe_format);}void __exit exit_pe_binfmt(void){	/* Remove the COFF and ELF loaders. */	unregister_binfmt(&pe_format);}#endif

⌨️ 快捷键说明

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