当前位置: 首页 > news >正文

从事网站开发方向舆情监测系统排名

从事网站开发方向,舆情监测系统排名,宝安中心区房价走势,上饶专业做网站建设本文主要讨论 mmap 函数以及如何使用 mmap 函数来加载一个 ELF 的可加载段。 01纠错 Android 8 及以后是会读取 section header 的,但不是所有的 section 都会读取。 https://cs.android.com/android/platform/superproject/main//main:bionic/linker/linker_phdr…

本文主要讨论 mmap 函数以及如何使用 mmap 函数来加载一个 ELF 的可加载段。

01纠错

Android 8 及以后是会读取 section header 的,但不是所有的 section 都会读取。

https://cs.android.com/android/platform/superproject/main/+/main:bionic/linker/linker_phdr.cpp;l=29?q=linker_phdr&sq=&ss=android

Android 8 应该是一个分水岭,可以看到会有很多版本检查逻辑:

mmap 函数

这个函数的参数在  man7 里面有非常详细的说明,建议看看:

https://man7.org/linux/man-pages/man2/mmap.2.html

看一个例子:

#include <stdio.h>
#include <sys/mman.h>
#include <dlfcn.h>int main()
{FILE *fp = fopen("/data/local/tmp/four.bin", "rb");void *addr = mmap((void *)0x80000000, 0x100, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_FIXED, fileno(fp), 0);fclose(fp);printf("%p\n", addr);printf("%08x\n", *(__uint8_t *)0x80000000);return 0;
}

需要注意的是,我们这里是脱离了Android Studio 来编写一个可执行程序,所以需要先搭建一下环境:

需要2个额外的文件来做交叉编译,试了下直接使用 aarch64-linux-gnu-gcc 编译出来的也无法执行,似乎必须得使用 ndk + cmake 来编译,不深入研究了,能跑就行。

2个额外文件的代码就不贴了,会上传到github上的 elf 文件夹里面。

https://github.com/aprz512/Android-Crack

将编译好的文件push到 /data/local/tmp/ 文件夹下,测试各个参数的作用。

第一个参数

第一个参数表示我们期望映射的地址,但是os并不一定会映射到这个地址,文档里面也说了,linux会选择一个页对齐的地址返回,如果该地址被占用了,会返回一个其他的地址。

第二个参数

第二个参数是映射的长度,这个很值得研究,需要分情况讨论。

我们以 four.bin 为例,该文件里面就只有 3 个字符串数字,大小为4个字节:

echo "123" > four.bin

当mmap传递的参数小于文件大小时,我们修改代码,将第二个参数的值改为2:

void *addr = mmap((void *)0x80000000, 0x2, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_FIXED, fileno(fp), 0);

尝试访问 0x80000002 处的地址,按照直觉来说,这个位置没有被分配,所以应该会出现 Segmentation fault 之类的错误。但是实际上并没有,输出结果为:

0x80000000
00000033

0x33对应的ascii就是字符“3”,这说明,它将整个文件都映射进去了,其实mmap是按照页来映射的,以 4KB 为单位。我们可以使用 IDA 验证一下,使用  getchar 卡住程序,然后调试程序:

可以看到 0x80000000 开始的位置确实是 four.bin 文件的数据。往下看直到 0x80000FFF的位置都是0值,从 0x80001000开始就不是进程空间地址了。

我们再做一个实验,将映射长度改为8KB,访问4KB+1的位置会如何呢?

0x80000000
00000033
Bus error

可以看到,访问 0x80000002 位置依然没有问题,但是访问 0x80001000 位置却出现了 Bus error。这个文档里面也说明了,出现这个错误是因为访问了超出文件映射结尾的页地址导致的。

我们看下 IDA 情况:

可以看到,后面的一页都是问号,访问这里面的虚拟地址就会出现 bus error。

第三个参数

权限标志位,没啥好说的,不如看文档。

需要注意的是,这里我们先全给 RWX,因为需要重定位,否则会报错。

第四个参数

只说一个MAP_FIXED,前面说到第一个参数的时候,我们传递了一个值给os,可是os不一定理我们。但是有些情况我们一定要os映射到指定的位置才行,比如段的加载。elf里面有 .text / .data 段,这两个段之间是有关系的,它们之间存在相互引用,如果不将这两个玩意挨着放,那么它们之间的一些相对偏移就会出问题。

所以,如何解决这个问题呢?就是传递 MAP_FIXED 标志位,它表示如果不能映射到我们指定的位置,干脆就直接失败。

加载段

好了,有了上面的基础,我们就可以自己实现 elf 的段加载了,其实就是调用 mmap 函数,将可加载段映射一下就完事。

不过需要考虑的事情有:当文件大小小于内存大小的时候,要怎么解决?

上面我们已经验证过了,如果直接映射会出 bus error。

所以,我们可以分两次映射,第二次映射一个匿名文件,是不是想到 maps 里面没名字的那一行了。

我们可以先看 linker 源码学习一下。

linker 源码

https://github.com/aosp-mirror/platform_bionic/blob/donut-release2/linker/linker.c

由于linker的核心代码变化不会太大,所以强烈建议研究老版本的源码,弄清楚了再去看新版本的。

这里有一个图:

示例代码

#include <stdio.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <stdlib.h>
#include <string.h>
#include <elf.h>#define PAGE_SIZE (4096)
#define PAGE_MASK (PAGE_SIZE - 1)
#define BASE (0x80000000)int main()
{// FILE *fp = fopen("/data/local/tmp/four.bin", "rb");// void *addr = mmap((void *)0x80000000, 0x2000, PROT_EXEC | PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_FIXED, fileno(fp), 0);// fclose(fp);// printf("%p\n", addr);// printf("%08x\n", *(__uint8_t *)0x80000002);// // printf("%08x\n", *(__uint8_t *)0x80001000);// getchar();size_t elf64_header = sizeof(Elf64_Ehdr);Elf64_Ehdr *ehdr = (Elf64_Ehdr *)malloc(elf64_header);FILE *fp = fopen("/data/local/tmp/ls", "rb");// read Elf64_Ehdr bytesfread(ehdr, elf64_header, 1, fp);printf("e_phoff: %08x\n", ehdr->e_phoff);size_t elf64_phdr = sizeof(Elf64_Phdr);int phdr_num = ehdr->e_phnum;printf("phdr_num: %d\n", phdr_num);Elf64_Phdr *phdr = (Elf64_Phdr *)malloc(elf64_phdr * phdr_num);fseek(fp, ehdr->e_phoff, SEEK_SET);fread(phdr, elf64_phdr * phdr_num, 1, fp);uint64_t len;uint64_t tmp;uint64_t pbase;uint64_t extra_len;uint64_t extra_base;for (size_t i = 0; i < phdr_num; i++){// printf("p_type: %d\n", phdr->p_type);if (phdr->p_type == PT_LOAD){// 这里计算的是 pbase 的值tmp = BASE + phdr->p_vaddr & (~PAGE_MASK);// 看图可知,这里的文件大小加上 ( base + p_vaddr - pbase),也就是 mask off 的值len = phdr->p_filesz + (phdr->p_vaddr & PAGE_MASK);pbase = mmap(tmp,len,PROT_EXEC | PROT_WRITE | PROT_READ,MAP_PRIVATE | MAP_FIXED,fileno(fp),phdr->p_offset & (~PAGE_MASK));printf("mapped addr: %08x, %08x\n", pbase, len);tmp = (unsigned char *)(((unsigned)pbase + len + PAGE_SIZE - 1) & (~PAGE_MASK));if (tmp < (BASE + phdr->p_vaddr + phdr->p_memsz)){extra_len = BASE + phdr->p_vaddr + phdr->p_memsz - tmp;extra_base = mmap((void *)tmp, extra_len,PROT_EXEC | PROT_WRITE | PROT_READ,MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS,-1, 0);printf("mapped addr: %08x, %08x\n", extra_base, extra_len);}}phdr++;}free(ehdr);free(phdr);fclose(fp);printf("mapped ok!!!");return 0;
}

运行结果如下:

sailfish:/data/local/tmp # ./elf                                       
e_phoff: 00000040
phdr_num: 9
mapped addr: 80000000, 0005c45c
mapped addr: 8005d000, 000047a0
mapped addr: 80062000, 00003966

http://www.tj-hxxt.cn/news/16587.html

相关文章:

  • 石家庄seo网站优化电话怎么制作seo搜索优化
  • 做采集的网站有流量吗关键词首页优化
  • 政府机关网站制作模板广告关键词
  • 浙江建设厅特种考试查询郑州百度推广seo
  • 广州做网站多少钱seo关键词推广怎么做
  • 上海产品设计公司seo网站推广软件排名
  • 网上做家教的网站卫星电视安装视频
  • 网站怎样做没有病毒竞价托管代运营
  • 吉林响应式网站建设百度文库官网入口
  • 帝国cms做网站软文100字左右案例
  • 做机械的专业外贸网站有哪些百度手机版网页
  • 模板免费网站seo超级外链工具
  • 杭州做网站吧百度竞价点击一次多少钱
  • 酒店网站建设2023年8月疫情严重吗
  • 如何做网站安全加固企业网站的作用有哪些
  • 企业如何注册自己的网站汕头seo快速排名
  • 遵义市网站制作代做百度关键词排名
  • 上海官网网址商丘搜索引擎优化
  • php网站开发费用江阴网站制作公司
  • 企业每年向工商网站做申报东莞网站营销策划
  • 巴适网站建设路由器优化大师
  • 无锡企业网站公司互联网销售可以卖什么产品
  • 网络推广培训学院电脑优化系统的软件哪个好
  • 外贸商城网站建站推广注册app赚钱平台
  • wordpress评论嵌套seo关键词排名优化方法
  • 英语网站online优化的近义词
  • 怎样建立自己网站难吗软文广告成功案例
  • 深圳公司注册办理流程seo公司品牌哪家好
  • 京东联盟的网站怎么做百度推广seo是什么意思
  • 织梦网站后台密码活动推广方式