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

网站建设广金手指六六十四黑龙江住房和城乡建设厅网站首页

网站建设广金手指六六十四,黑龙江住房和城乡建设厅网站首页,免费网站模板 下载,中国价格网前言 当在 linux 命令行中 ./ 运行一个程序时#xff0c;实际上操作系统会调用加载器将这个程序加载到内存中去执行。为了探究加载器的行为#xff0c;今天我们就自己动手写一个简单的加载器。 工作原理 加载器的工作原理#xff1a; 从磁盘读取 bin 文件到内存#xf…前言 当在 linux 命令行中 ./ 运行一个程序时实际上操作系统会调用加载器将这个程序加载到内存中去执行。为了探究加载器的行为今天我们就自己动手写一个简单的加载器。 工作原理 加载器的工作原理 从磁盘读取 bin 文件到内存bin 文件包含的是 CPU 可以直接执行的指令跳转到该内存的起始地址 就这么简单。 理论是比较简单的但工程实践上可能会遇到各种各样的问题我们只要围绕主线遇神杀神遇魔杀魔就可以了。千万不要花过多精力去打副本如果你精力很旺盛当我没说。 上面讲会遇到各种各样的问题这里不是为了劝退而是想让大家跟着我一起披荆斩棘抵达终点享受整个过程。 bin 程序 在写加载器之前我们先写一个 bin 程序不然我们徒有加载器也无法验证其是否能够工作。 bin 程序的功能也很简单就是向标准输出打印一行字符串。 由于我们计划写的加载器功能比较简单所以我们写的 bin 程序也要尽可能简单不要有依赖的动态库。 minimal.S .global _start _start:movq $1, %rax // write (movq $1, %rdi // fd 1,lea buf(%rip), %rsi // buf,movq $(buf_end - buf), %rdx // count buf_end - bufsyscall // );movq $60, %rax // exit (movq $0, %rdi // status 0syscall // );buf:.ascii hello world\nbuf_end: Makefile minimal: minimal.Sgcc -S minimal.S minimal.sas minimal.s -o minimal.old minimal.o -o $objcopy -O binary --only-section.text minimal minimal.bin上面的代码用 C 语言写出来就是下面两行 sys_write(1, buf, count); sys_exit(0);解释下上面的汇编代码 系统调用号通过 rax 传递其余参数传递顺序为rdirsirdxr10r8r9。 加载器代码 根据上面介绍的工作原理下面开始写加载器 loader.c #include stdio.h #include stdlib.hint main(int argc, char *argv[]) {FILE *f;char *buffer;long file_size;if (argc 2) {printf(Usage: %s filename\n, argv[0]);return 1;}// 打开二进制文件f fopen(argv[1], rb);if (!f) {printf(Error: could not open file %s\n, argv[1]);return 1;}// 获取文件大小fseek(f, 0, SEEK_END);file_size ftell(f);fseek(f, 0, SEEK_SET);// 分配内存并读取文件内容buffer (char *)malloc(file_size);if (!buffer) {printf(Error: could not allocate memory\n);fclose(f);return 1;}fread(buffer, file_size, 1, f);// 关闭文件fclose(f);// 转移到二进制文件的入口点void (*entry_point)() (void (*)())buffer;entry_point();// 释放内存free(buffer);return 0; }编译运行 $ gcc -g -o loader loader.c $ ./loader ../loader/minimal.bin 段错误 (核心已转储)出现了段错误 定位错误 使用 gdb 定位出错位置 Reading symbols from ./loader... (gdb) set args ../loader/minimal.bin (gdb) run Starting program: /home/liyongjun/project/c/C_study/others/loader2/loader ../loader/minimal.binProgram received signal SIGSEGV, Segmentation fault. 0x000055555555a490 in ?? ()loader 是使用 -g 选项编译出来的如果出错位置在 loader 中gdb 会定位到出错的代码行上面显然没有那只有一个原因loader 已经跳转到 minimal.bin 开始执行了出错位置在 minimal.bin 中。 继续使用 gdb 单步调试一下 34 fread(buffer, file_size, 1, f); (gdb) 37 fclose(f); (gdb) 40 void (*entry_point)() (void (*)())buffer; (gdb) 41 entry_point(); (gdb) p/x buffer $1 0x55555555a490 (gdb) nProgram received signal SIGSEGV, Segmentation fault. 0x000055555555a490 in ?? () (gdb) 确实出错位置在 bin 程序的入口。 并且出错时收到了信号 SIGSEGV一般收到该信号是代码访问了空指针、内存越界等。显然我们不属于以上情况。 经过查阅资料得知如果想执行某处内存的代码那么该内存需要具有可执行权限。 所以收到 SIGSEGV 信号原来是执行了不具有可执行权限的内存代码。 给内存加权限 知道原因就好办了那就给内存加上可执行权限呗。 在 Linux 中mprotect() 函数可以用来修改一段指定内存区域的保护属性。 参考Linux中mprotect()函数的用法 完善代码 // 将内存页的保护属性修改为可读、可写、可执行if (mprotect(buffer, file_size, PROT_READ | PROT_WRITE | PROT_EXEC) ! 0) {perror(Failed to set memory protection);free(buffer);return 1;}执行有报错了 $ ./loader ../loader/minimal.bin Failed to set memory protection: Invalid argument无法给 buffer 赋予可执行权限。 查阅资料得知 mprotect 的参数分别为内存区间的地址区间的大小新的保护标志设置。所指定的内存区间必须包含整个页区间地址必须和整个系统页大小对齐而区间长度必须是页大小的整数倍。 继续改进代码 #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/mman.hstruct mem_align {void *origin_start; // for freevoid *start; // data addr start, align page sizevoid *end; // data addr end, align page sizevoid *origin_end; };int malloc_align_page(size_t memsize, struct mem_align *mem) {if (memsize 0 || mem NULL)return -1;memset(mem, 0, sizeof(*mem));long pagesize sysconf(_SC_PAGE_SIZE);if (pagesize -1) {perror(sysconf err);return -1;}size_t datasize memsize pagesize * 2;mem-origin_start malloc(datasize);if (mem-origin_start NULL)return -1;mem-origin_end mem-origin_start datasize;long mask pagesize - 1;mem-start (void *)((long)(mem-origin_start pagesize) ~mask);long pagenum memsize / pagesize 1;mem-end mem-start pagesize * pagenum;return 0; }int main(int argc, char *argv[]) {FILE *f;char *buffer;long file_size;struct mem_align mem;int ret;if (argc 2) {printf(Usage: %s filename\n, argv[0]);return 1;}// 打开二进制文件f fopen(argv[1], rb);if (!f) {printf(Error: could not open file %s\n, argv[1]);return 1;}// 获取文件大小fseek(f, 0, SEEK_END);file_size ftell(f);fseek(f, 0, SEEK_SET);ret malloc_align_page(file_size, mem);if (ret ! 0) {printf(malloc error\n);fclose(f);return 1;}fread(mem.start, file_size, 1, f);// 关闭文件fclose(f);// 将内存页的保护属性修改为可读、可写、可执行if (mprotect(mem.start, file_size, PROT_READ | PROT_WRITE | PROT_EXEC) ! 0) {perror(Failed to set memory protection);free(mem.origin_start);return 1;}// 转移到二进制文件的入口点void (*entry_point)() (void (*)())mem.start;entry_point();// 释放内存free(mem.origin_start);return 0; }执行 $ ./loader ../loader/minimal.bin hello world成功加载了 minimal.bin并执行成功。✌✌✌ 权限探索 在 loader.c 加些打印并让程序暂停我们去查看下内存情况 loader.c #include stdio.h #include stdlib.h #include string.h #include unistd.h #include sys/mman.hstruct mem_align {void *origin_start; // for freevoid *start; // data addr start, align page sizevoid *end; // data addr end, align page sizevoid *origin_end; };int malloc_align_page(size_t memsize, struct mem_align *mem) {if (memsize 0 || mem NULL)return -1;memset(mem, 0, sizeof(*mem));long pagesize sysconf(_SC_PAGE_SIZE);if (pagesize -1) {perror(sysconf err);return -1;}printf(pagesize : 0x%lx\n, pagesize);size_t datasize memsize pagesize * 2;mem-origin_start malloc(datasize);if (mem-origin_start NULL)return -1;mem-origin_end mem-origin_start datasize;long mask pagesize - 1;mem-start (void *)((long)(mem-origin_start pagesize) ~mask);long pagenum memsize / pagesize 1;mem-end mem-start pagesize * pagenum;return 0; }int main(int argc, char *argv[]) {FILE *f;char *buffer;long file_size;struct mem_align mem;int ret;if (argc 2) {printf(Usage: %s filename\n, argv[0]);return 1;}// 打开二进制文件f fopen(argv[1], rb);if (!f) {printf(Error: could not open file %s\n, argv[1]);return 1;}// 获取文件大小fseek(f, 0, SEEK_END);file_size ftell(f);fseek(f, 0, SEEK_SET);ret malloc_align_page(file_size, mem);if (ret ! 0) {printf(malloc error\n);fclose(f);return 1;}fread(mem.start, file_size, 1, f);printf(mem start : %p\n, mem.start);printf(mem end : %p\n, mem.end);printf(mem origin_start : %p\n, mem.origin_start);printf(mem origin_end : %p\n, mem.origin_end);// 关闭文件fclose(f);// 将内存页的保护属性修改为可读、可写、可执行if (mprotect(mem.start, file_size, PROT_READ | PROT_WRITE | PROT_EXEC) ! 0) {perror(Failed to set memory protection);free(mem.origin_start);return 1;}sleep(600);// 转移到二进制文件的入口点void (*entry_point)() (void (*)())mem.start;entry_point();// 释放内存free(mem.origin_start);return 0; }运行 $ ./loader ../loader/minimal.bin pagesize : 0x1000 mem start : 0x55fd6152f000 mem end : 0x55fd61530000 mem origin_start : 0x55fd6152e8a0 mem origin_end : 0x55fd615308da$ ps -ef | grep loader liyongj 1656575 1625198 0 12:45 pts/121 00:00:00 ./loader …/loader/minimal.bin liyongjunBox:/proc/1656575$ cat /proc/1656575/maps 55fd5fe51000-55fd5fe52000 r–p 00000000 08:05 3244524 /home/liyongjun/project/c/C_study/others/loader2/loader 55fd5fe52000-55fd5fe53000 r-xp 00001000 08:05 3244524 /home/liyongjun/project/c/C_study/others/loader2/loader 55fd5fe53000-55fd5fe54000 r–p 00002000 08:05 3244524 /home/liyongjun/project/c/C_study/others/loader2/loader 55fd5fe54000-55fd5fe55000 r–p 00002000 08:05 3244524 /home/liyongjun/project/c/C_study/others/loader2/loader 55fd5fe55000-55fd5fe56000 rw-p 00003000 08:05 3244524 /home/liyongjun/project/c/C_study/others/loader2/loader 55fd6152d000-55fd6152f000 rw-p 00000000 00:00 0 [heap] 55fd6152f000-55fd61530000 rwxp 00000000 00:00 0 [heap] 55fd61530000-55fd6154e000 rw-p 00000000 00:00 0 [heap] 7f3c24b32000-7f3c24b54000 r–p 00000000 08:05 658174 /usr/lib/x86_64-linux-gnu/libc-2.31.so 7f3c24b54000-7f3c24ccc000 r-xp 00022000 08:05 658174 /usr/lib/x86_64-linux-gnu/libc-2.31.so 7f3c24ccc000-7f3c24d1a000 r–p 0019a000 08:05 658174 /usr/lib/x86_64-linux-gnu/libc-2.31.so 7f3c24d1a000-7f3c24d1e000 r–p 001e7000 08:05 658174 /usr/lib/x86_64-linux-gnu/libc-2.31.so 7f3c24d1e000-7f3c24d20000 rw-p 001eb000 08:05 658174 /usr/lib/x86_64-linux-gnu/libc-2.31.so 7f3c24d20000-7f3c24d26000 rw-p 00000000 00:00 0 7f3c24d40000-7f3c24d41000 r–p 00000000 08:05 658162 /usr/lib/x86_64-linux-gnu/ld-2.31.so 7f3c24d41000-7f3c24d64000 r-xp 00001000 08:05 658162 /usr/lib/x86_64-linux-gnu/ld-2.31.so 7f3c24d64000-7f3c24d6c000 r–p 00024000 08:05 658162 /usr/lib/x86_64-linux-gnu/ld-2.31.so 7f3c24d6d000-7f3c24d6e000 r–p 0002c000 08:05 658162 /usr/lib/x86_64-linux-gnu/ld-2.31.so 7f3c24d6e000-7f3c24d6f000 rw-p 0002d000 08:05 658162 /usr/lib/x86_64-linux-gnu/ld-2.31.so 7f3c24d6f000-7f3c24d70000 rw-p 00000000 00:00 0 7ffec3fac000-7ffec3fce000 rw-p 00000000 00:00 0 [stack] 7ffec3fe1000-7ffec3fe5000 r–p 00000000 00:00 0 [vvar] 7ffec3fe5000-7ffec3fe7000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall] 0x55fd6152f000 ~ 0x55fd61530000是我们使用 malloc 从堆 (heap) 申请的内存已经被我们赋予了可执行 (x) 权限。 over
http://www.hkea.cn/news/14581852/

相关文章:

  • 互联网电商网站建设建设通网站官网
  • 建设论坛网站用什么cms校园服装网站建设预算
  • 一起来做网站17中企动力科技股份有限公司淄博分公司
  • 网站界面设计形考任务服装网站设计欣赏
  • 国外 作品集 网站微信运营管理软件
  • 做电商平台网站网站建设需要多大的空间
  • 律师事务所网站制作网络开发公司是干什么的
  • 在线制作gif小红书seo排名规则
  • 做电脑网站用什么软件好用软文发稿网
  • 茶叶建设网站的优势长沙建设网站公司
  • 找货源的网上平台有哪些西安seo代理计费
  • 上海高端建站网站上海十大室内设计公司排名
  • 个人网站建设公司免费推广广告链接
  • 电商网站平台建设方案爱站网长尾关键词挖掘工具下载
  • 重庆网站开发企业页面跳转请记住新域名
  • seo站内优化包括合肥租房网
  • 阿里巴巴国际站怎么做网站模版网站建设开发报告论文
  • 山东临沂网站推广怎么营销自己的产品
  • 贵阳建设工程招聘信息网站国外一个做ppt的网站
  • 河北建设机械协会网站网站建设公司 预算
  • 有做机械工装的网站吗网站代码在哪里看
  • 手机微网站怎么制作的vps centos wordpress
  • 易语言做网站登录东营城乡建设局官网
  • 玉门市住房和城乡建设局网站上海网站建设公司sky
  • 泰和网站制作成全视频免费高清观看在线韩剧
  • 周大福网站建设主要工作网站色彩策划
  • 为自己做的网站申请域名链接转换器
  • 湖南城乡建设部网站wordpress qq主题
  • 网站关键词建设wordpress怎么加js文件路径
  • 网站栏目定位中国储备粮管理集团有限公司