操作系统内核加载随机化记录器

操作系统内核加载随机化记录器

目标

记录随机化加载地址,信息存放到日志文件。

实现方法:分析内核源码中地址随机化的位置与原理,对随机化后的地址进行记录。

实验环境:

基于Linux ubuntu 4.4.0-31-generic #50~14.04.1-Ubuntu的Ubuntu7.0运行环境

Linux4.20+qemu开发环境

参考文档:
https://www.cnblogs.com/wangaohui/p/7122653.html

https://blog.csdn.net/gatieme/article/details/51594439

实验方法

抓住进程地址随机化两个关键点:一是记录进程加载地址信息的关键结构体,二是进程执行关键函数。

有关进程的关键结构体为vm_area_struct,具体如下,其中即记录了相应的vm_start地址。

struct vm_area_struct {
	/* The first cache line has the info for VMA tree walking. */

	unsigned long vm_start;		/* Our start address within vm_mm. */
	unsigned long vm_end;		/* The first byte after our end address
					   within vm_mm. */

	/* linked list of VM areas per task, sorted by address */
	struct vm_area_struct *vm_next, *vm_prev;

	struct rb_node vm_rb;

	/*
	 * Largest free memory gap in bytes to the left of this VMA.
	 * Either between this VMA and vma->vm_prev, or between one of the
	 * VMAs below us in the VMA rbtree and its ->vm_prev. This helps
	 * get_unmapped_area find a free area of the right size.
	 */
	unsigned long rb_subtree_gap;

	/* Second cache line starts here. */

	struct mm_struct *vm_mm;	/* The address space we belong to. */
	pgprot_t vm_page_prot;		/* Access permissions of this VMA. */
	unsigned long vm_flags;		/* Flags, see mm.h. */

	/*
	 * For areas with an address space and backing store,
	 * linkage into the address_space->i_mmap interval tree.
	 */
	struct {
		struct rb_node rb;
		unsigned long rb_subtree_last;
	} shared;

	/*
	 * A file's MAP_PRIVATE vma can be in both i_mmap tree and anon_vma
	 * list, after a COW of one of the file pages.	A MAP_SHARED vma
	 * can only be in the i_mmap tree.  An anonymous MAP_PRIVATE, stack
	 * or brk vma (with NULL file) can only be in an anon_vma list.
	 */
	struct list_head anon_vma_chain; /* Serialized by mmap_sem &
					  * page_table_lock */
	struct anon_vma *anon_vma;	/* Serialized by page_table_lock */

	/* Function pointers to deal with this struct. */
	const struct vm_operations_struct *vm_ops;

	/* Information about our backing store: */
	unsigned long vm_pgoff;		/* Offset (within vm_file) in PAGE_SIZE
					   units, *not* PAGE_CACHE_SIZE */
	struct file * vm_file;		/* File we map to (can be NULL). */
	void * vm_private_data;		/* was vm_pte (shared mem) */

#ifndef CONFIG_MMU
	struct vm_region *vm_region;	/* NOMMU mapping region */
#endif
#ifdef CONFIG_NUMA
	struct mempolicy *vm_policy;	/* NUMA policy for the VMA */
#endif
};

进程执行关键函数为do_execve,其中使用了关键结构体linux_binprm ,如下所示

struct linux_binprm {
	char buf[BINPRM_BUF_SIZE];
#ifdef CONFIG_MMU
	struct vm_area_struct *vma;
	unsigned long vma_pages;
#else
# define MAX_ARG_PAGES	32
	struct page *page[MAX_ARG_PAGES];
#endif
	struct mm_struct *mm;
	unsigned long p; /* current top of mem */
	unsigned int
		cred_prepared:1,/* true if creds already prepared (multiple
				 * preps happen for interpreters) */
		cap_effective:1;/* true if has elevated effective capabilities,
				 * false if not; except for init which inherits
				 * its parent's caps anyway */
#ifdef __alpha__
	unsigned int taso:1;
#endif
	unsigned int recursion_depth; /* only for search_binary_handler() */
	struct file * file;
	struct cred *cred;	/* new credentials */
	int unsafe;		/* how unsafe this exec is (mask of LSM_UNSAFE_*) */
	unsigned int per_clear;	/* bits to clear in current->personality */
	int argc, envc;
	const char * filename;	/* Name of binary as seen by procps */
	const char * interp;	/* Name of the binary really executed. Most
				   of the time same as filename, but could be
				   different for binfmt_{misc,script} */
	unsigned interp_flags;
	unsigned interp_data;
	unsigned long loader, exec;
};

分析其调用顺序,

linux-4.2\fs\exec.c               __do_execve_file()

linux-4.2\fs\exec.c               exec_binprm()

linux-4.2\fs\exec.c               search_binary_handler()

linux-4.2\fs\binfmt_elf.c       load_elf_binary()

linux-4.2\fs\exec.c               setup_new_exec(bprm)

linux-4.2\arch\x86\mm\mmap.c       arch_pick_mmap_layout(current->mm)

可逐步找到地址随机化的关键函数:arch_pick_mmap_layout。

void arch_pick_mmap_layout(struct mm_struct *mm)
{
	unsigned long random_factor = 0UL;

	if (current->flags & PF_RANDOMIZE)
		random_factor = arch_mmap_rnd();

	mm->mmap_legacy_base = mmap_legacy_base(random_factor);

	if (mmap_is_legacy()) {
		mm->mmap_base = mm->mmap_legacy_base;
		mm->get_unmapped_area = arch_get_unmapped_area;
	} else {
		mm->mmap_base = mmap_base(random_factor);
		mm->get_unmapped_area = arch_get_unmapped_area_topdown;
	}
}

堆栈随机化函数为

retval = setup_arg_pages(bprm, randomize_stack_top(STACK_TOP), executable_stack);

通过GDB调试可查看其随机化的结果,如下图所示。

 可通过命令行获取随机化后的地址,如图所示,

与实验获取结果进行对比,地址相同,实验成功。

 源码

static int load_elf_binary(struct linux_binprm *bprm)
{  
/*
原始代码
*/ 
    struct file *fp;
    mm_segment_t fs;
    loff_t my_pos;
    int filename_size;
    char * file_str = NULL;
    struct timex  txc;
    struct rtc_time tm;
/*
**原始代码
#ifdef ELF_PLAT_INIT
	ELF_PLAT_INIT(regs, reloc_func_desc);
#endif
**/
    filename_size = 1024;  
		
    file_str = kmalloc(filename_size , GFP_KERNEL);
    if(file_str == NULL)
    {       
        goto end;
    }
    memset(file_str, 0, filename_size );
	    
    do_gettimeofday(&(txc.time));
    rtc_time_to_tm(txc.time.tv_sec,&tm);
	    
    sprintf(file_str,"UTC time :%d-%02d-%02d %02d:%02d:%02d;filename: %s ;vm_start :0x%lx         \n",tm.tm_year+1900,tm.tm_mon,         tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec,bprm->filename,bprm->vma->vm_start);
	    
    fp = filp_open("/address_file",O_RDWR |O_CREAT| O_APPEND ,0777);
    if (IS_ERR(fp)){
        goto end;
    }
    my_pos = 0;
    fs = get_fs();
    set_fs(KERNEL_DS);
    vfs_write(fp,file_str, strlen(file_str),&my_pos);
    filp_close(fp,NULL);    
    set_fs(fs);
end:
    if(file_str != NULL)
    {   
	kfree(file_str);
    }	
    /**原始代码*/
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值