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

📄 sysdll.c

📁 该项目主要是将wingdows程序直接运行在linux上
💻 C
字号:
/* * sysdll.c * * Copyright (C) 2006  Insigme Co., Ltd * * Authors: * - Chenzhan Hu * * This software has been developed while working on the Linux Unified Kernel * project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute, * which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn). * * The project is sponsored by Insigma Co., Ltd. * * The authors can be reached at linux@insigma.com.cn. * * This program is free software; you can redistribute it and/or modify it * under the terms of  the GNU General  Public License as published by the * Free Software Foundation; either version 2 of the  License, or (at your * option) any later version. * * Revision History: *   Jan 2006 - Created. *//* * sysdll.c: * Reference to Reactos Kernel code */#include <linux/win32_process.h>#include <linux/win32_thread.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/file.h>#include <asm/mman.h>#include <asm/uaccess.h>#include "win32.h"#include "thread.h"#include "object.h"#include "pefile.h"#include "file.h"#include "section.h"#include "mm/attach.h"#ifdef CONFIG_UNIFIED_KERNEL#define RTL_CONSTANT_STRING(s) { sizeof(s) - sizeof((s)[0]), sizeof(s), (s) }#define InitializeObjectAttributes(p,n,a,r,s) { \	(p)->Length = sizeof(OBJECT_ATTRIBUTES); \	(p)->RootDirectory = (r); \	(p)->Attributes = (a); \	(p)->ObjectName = (n); \	(p)->SecurityDescriptor = (s); \	(p)->SecurityQualityOfService = NULL; \}#if ELF_CLASS == ELFCLASS32#define elf_shdr		Elf32_Shdr#define elf_sym			elf32_sym#define	elf_off_t		Elf32_Off#define	elf_half_t		Elf32_Half#else#define elf_shdr		Elf64_Shdr#define elf_sym			elf64_sym#define	elf_off_t		Elf64_Off#define	elf_half_t		Elf64_Half#endifelf_off_t ntdll_phoff;elf_half_t ntdll_phnum;#define ELF_EXEC_PAGESIZE	4096#if ELF_EXEC_PAGESIZE > PAGE_SIZE# define ELF_MIN_ALIGN	ELF_EXEC_PAGESIZE#else# define ELF_MIN_ALIGN	PAGE_SIZE#endif#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_MIN_ALIGN-1))#define ELF_PAGEOFFSET(_v) ((_v) & (ELF_MIN_ALIGN-1))#define ELF_PAGEALIGN(_v) (((_v) + ELF_MIN_ALIGN - 1) & ~(ELF_MIN_ALIGN - 1))extern unsigned long win32_do_mmap_pgoff(struct task_struct *task, char topdown,		struct file *file, unsigned long addr, unsigned long len,		unsigned long prot, unsigned long flags, unsigned long pgoff);static int padzero(task_t *tsk, unsigned long bss){	int ret = 0;	unsigned long nbyte;	struct mm_struct *mm = NULL;	nbyte = ELF_PAGEOFFSET(bss);	if (nbyte) {		nbyte = ELF_MIN_ALIGN - nbyte;		if (tsk == current) {			if (clear_user((void __user *) bss, nbyte))				ret = -EFAULT;		}		else {			struct eprocess *process = tsk->ethread->threads_process;			mm = KeAttachProcess(&process->pcb);			if (clear_user((void __user *) bss, nbyte))				ret = -EFAULT;			KeDetachProcess(mm);		}	}	return ret;}static inline unsigned long win32_do_mmap(struct task_struct *tsk, char topdown,		struct file *file, unsigned long addr, unsigned long len,		unsigned long prot, unsigned long flag, unsigned long offset){	unsigned long ret = -EINVAL;	if ((offset + PAGE_ALIGN(len)) < offset)		goto out;	if (!(offset & ~PAGE_MASK))		ret = win32_do_mmap_pgoff(tsk, topdown, file, addr, len, prot, flag, offset >> PAGE_SHIFT);out:	return ret;} /* end win32_do_mmap */static unsigned long elf_map(struct task_struct *tsk, struct file *filep,		unsigned long addr, struct elf_phdr *eppnt, int prot, int type){	unsigned long map_addr;	down_write(&tsk->mm->mmap_sem);	map_addr = tsk == current		? do_mmap(filep, ELF_PAGESTART(addr),			   eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,			   eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr))		: win32_do_mmap(tsk, 0, filep, ELF_PAGESTART(addr),			   eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr), prot, type,			   eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr));	up_write(&tsk->mm->mmap_sem);	return map_addr;} /* end elf_map */static unsigned long load_elf_interp(task_t *tsk,		struct elfhdr * interp_elf_ex,		struct file * interpreter,		unsigned long *interp_load_addr,		char *ld_name){	struct elf_phdr *elf_phdata;	struct elf_phdr *eppnt;	unsigned long load_addr = 0;	int load_addr_set = 0;	unsigned long last_bss = 0, elf_bss = 0;	unsigned long error = ~0UL;	int retval, i, size;	/* First of all, some simple consistency checks */	if (interp_elf_ex->e_type != ET_EXEC &&			interp_elf_ex->e_type != ET_DYN)		goto out;	if (!elf_check_arch(interp_elf_ex))		goto out;	if (!interpreter->f_op || !interpreter->f_op->mmap)		goto out;	/*	 * If the size of this structure has changed, then punt, since	 * we will be doing the wrong thing.	 */	if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))		goto out;	if (interp_elf_ex->e_phnum < 1 ||			interp_elf_ex->e_phnum > 65536U / sizeof(struct elf_phdr))		goto out;	/* Now read in all of the header information */	size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum;	if (size > ELF_MIN_ALIGN)		goto out;	elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL);	if (!elf_phdata)		goto out;	retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size);	error = -EIO;	if (retval != size) {		if (retval < 0)			error = retval;			goto out_close;	}	eppnt = elf_phdata;	for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {		if (eppnt->p_type == PT_INTERP && ld_name)			kernel_read(interpreter, eppnt->p_offset, ld_name, eppnt->p_filesz);		if (eppnt->p_type == PT_LOAD) {			int elf_type = MAP_PRIVATE | MAP_DENYWRITE;			int elf_prot = 0;			unsigned long vaddr = 0;			unsigned long k, map_addr;			if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ | PROT_WRITE;			if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;			if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;			vaddr = eppnt->p_vaddr;			if (interp_elf_ex->e_type == ET_EXEC || load_addr_set)				elf_type |= MAP_FIXED;			map_addr = elf_map(tsk, interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type);			error = map_addr;			if (map_addr > (unsigned long)TASK_SIZE)				goto out_close;			if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {				load_addr = map_addr - ELF_PAGESTART(vaddr);				*interp_load_addr = map_addr - eppnt->p_offset;				load_addr_set = 1;			}			/*			 * Check to see if the section's size will overflow the			 * allowed task size. Note that p_filesz must always be			 * <= p_memsize so it is only necessary to check p_memsz.			 */			k = load_addr + eppnt->p_vaddr;			if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz ||					eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) {				error = -ENOMEM;				goto out_close;			}			/*			 * Find the end of the file mapping for this phdr, and keep			 * track of the largest address we see for this.			 */			k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;			if (k > elf_bss)				elf_bss = k;			/*			 * Do the same thing for the memory mapping - between			 * elf_bss and last_bss is the bss section.			 */			k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;			if (k > last_bss)				last_bss = k;		}	}	/*	 * Now fill out the bss section.  First pad the last page up	 * to the page boundary, and then perform a mmap to make sure	 * that there are zero-mapped pages up to and including the 	 * last bss page.	 */	if (padzero(tsk, elf_bss)) {		error = -EFAULT;		goto out_close;	}	elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1);	/* What we have mapped so far */	/* Map the last of the bss segment */	if (last_bss > elf_bss) {		down_write(&tsk->mm->mmap_sem);		error = win32_do_mmap_pgoff(tsk, 0, NULL, elf_bss, last_bss - elf_bss,				PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, 0);		up_write(&tsk->mm->mmap_sem);		if (error > (unsigned long)TASK_SIZE)			goto out_close;	}	error = ((unsigned long) interp_elf_ex->e_entry) + load_addr;out_close:	kfree(elf_phdata);out:	return error;} /* end load_elf_interp */static int sym_count = 0;static unsigned long find_symbol(elf_shdr *elf_shdata, int shnum, char *sym){	int		link = -1;	int		str_tab_size = 0;	char	*str_tab = NULL;	elf_shdr	*elf_spnt;	struct elf_sym	*sympnt, *sym_tab = NULL;	unsigned long	sym_addr = -EINVAL;	for (elf_spnt = elf_shdata; elf_spnt < elf_shdata + shnum; elf_spnt++) {		if (elf_spnt->sh_type == SHT_DYNSYM) {			sym_tab = (struct elf_sym *)(elf_spnt->sh_addr);			link = elf_spnt->sh_link;			sym_count = elf_spnt->sh_size / sizeof(struct elf_sym);		}	}	if (link >= 0) {		elf_spnt = elf_shdata + link;		if (elf_spnt->sh_type != SHT_STRTAB)			return -ENOEXEC;		str_tab = (char *)(elf_spnt->sh_addr);		str_tab_size = elf_spnt->sh_size;	}	if (sym_tab && str_tab) {		for (sympnt = sym_tab; sympnt < sym_tab + sym_count; sympnt++) {			if (sympnt->st_name > str_tab_size)				break;			if (!strcmp(sympnt->st_name + str_tab, sym)) {				sym_addr = sympnt->st_value;				break;			}		}	}	return sym_addr;} /* end find_symbol */NTSTATUSSTDCALLLdrpInitializeSystemDll(VOID){	return 0;}static unsigned long ntdll_entry;static unsigned long interp_entry;static unsigned long pe_entry;static unsigned long start_thunk;static unsigned long apc_dispatcher;unsigned long get_ntdll_entry(void){	return ntdll_entry;}unsigned long get_apc_dispatcher(void){	return apc_dispatcher;}unsigned long get_pe_entry(void){	return pe_entry;}unsigned long get_interp_entry(void){	return interp_entry;}unsigned long get_start_thunk(void){	return start_thunk;}NTSTATUS STDCALL LdrpMapSystemDll(struct task_struct *tsk, char *name,		unsigned long *ntdll_load_addr, unsigned long *interp_load_addr){	NTSTATUS retval;	struct file *interpreter = NULL, *ntdll = NULL;	struct elfhdr	ntdll_elf_ex, interp_elf_ex;	char buf[BINPRM_BUF_SIZE];	char ld_name[32];	ntdll = open_exec(name);	retval = PTR_ERR(ntdll);	if (IS_ERR(ntdll))		goto out;	/* read 128 Byte ELF header */	retval = kernel_read(ntdll, 0, buf, BINPRM_BUF_SIZE);	if (retval != BINPRM_BUF_SIZE) {		if (retval >= 0)			retval = -EIO;		goto out_free_ntdll;	}	/* Get the exec headers */	ntdll_elf_ex = *((struct elfhdr *)buf);	ntdll_phoff = ntdll_elf_ex.e_phoff;	ntdll_phnum = ntdll_elf_ex.e_phnum;	load_elf_interp(tsk, &ntdll_elf_ex, ntdll, ntdll_load_addr, ld_name);	if (tsk == current) {		int elf_shnum;		int elf_shsize;		elf_shdr *elf_shdata = NULL;		/* section header is not mapped to memory, need read it */		/* load section header list for ntdll */		elf_shnum = ntdll_elf_ex.e_shnum;		elf_shsize = elf_shnum * ntdll_elf_ex.e_shentsize;		elf_shdata = (elf_shdr *)kmalloc(elf_shsize, GFP_KERNEL);		if (!elf_shdata) {			retval = -ENOMEM;			goto out_free_ntdll;		}		retval = kernel_read(ntdll, ntdll_elf_ex.e_shoff, (void *)elf_shdata, elf_shsize);		if (retval != elf_shsize) {			if (retval >= 0)				retval = -EIO;			kfree(elf_shdata);			goto out_free_ntdll;		}		/* LdrInitializeThunk is used to load dll for PE exe file */		ntdll_entry = find_symbol(elf_shdata, elf_shnum, "LdrInitializeThunk");		/* when interpreter done, jump to StartThunk */		start_thunk = find_symbol(elf_shdata, elf_shnum, "StartThunk");		/* KiUserApcDispatcher is APC Dispatcher */		apc_dispatcher = find_symbol(elf_shdata, elf_shnum, "KiUserApcDispatcher");		/* a forward function , will call BaseProcessStart in kernel32.dll.so */		pe_entry = find_symbol(elf_shdata, elf_shnum, "ProcessStartForward");		kfree(elf_shdata);	}	allow_write_access(ntdll);	fput(ntdll);	interpreter = open_exec(ld_name);	retval = PTR_ERR(interpreter);	if (IS_ERR(interpreter))		goto out;	retval = kernel_read(interpreter, 0, buf, BINPRM_BUF_SIZE);	if (retval != BINPRM_BUF_SIZE) {		if (retval >= 0)			retval = -EIO;		goto out_free_interp;	}	/* Get the exec headers */	interp_elf_ex = *((struct elfhdr *)buf);	interp_entry = load_elf_interp(tsk, &interp_elf_ex, interpreter, interp_load_addr, NULL);	allow_write_access(interpreter);	fput(interpreter);	retval = 0;out:	return retval;out_free_ntdll:	allow_write_access(ntdll);	if (ntdll)		fput(ntdll);	goto out;out_free_interp:	allow_write_access(interpreter);	if (interpreter)		fput(interpreter);	goto out;} /* end LdrpMapSystemDll */#endif

⌨️ 快捷键说明

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