加密SO文件中自定义的section
2015-10-14 18:01
344 查看
加密SO文件中自定义的section
作者: 0n1y3nd丶 分类: Android 发布时间:2014-08-29 18:22 ė 61条评论
前言
加密已知so文件中的某一section,在运行时解密。执行里面的代码!0×1
libsyc.so里有一个.textsection,里面有一个方法返回一个字符串!生成未加密的libsyc.so的代码:
123 | JNIEXPORT jstring returnString(JNIEnv* env, jclass cls){ return env->NewStringUTF("String From Native!");} |
0×2
加密代码加密的流程:打开so文件,读取elf头部数据,根据e.shoff定位到section header读取section header的数据,根据sh_offset定位到string table的位置遍历string table,根据section的名称找到需要加密的section找到之后,根据sh_offset和sh_size读取section里的数据到变量中加密加密之后的数据覆盖原位置的数据C++1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 | /* * encrypt_section.c * * Created on: 2014-8-29 * Author: lyz */ #include <stdio.h> #include <fcntl.h> #include <elf.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main(int argc, char** argv){ char section_name[] = ".textsection"; char *shstr = NULL; char *content = NULL; Elf32_Ehdr ehdr; Elf32_Shdr shdr; int i; unsigned int base, length; unsigned short nblock; unsigned short nsize; unsigned char block_size = 16; int fd; if(argc < 2){ puts("PLease input so file name!"); return -1; } fd = open(argv[1], O_RDWR); if(fd < 0){ printf("open %s failed!\n", argv[1]); goto _error; } printf("open %s success!\n", argv[1]); if(read(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)){ printf("Read Elf header failed!"); goto _error; } printf("Read Elf header success!\n"); lseek(fd, ehdr.e_shoff + sizeof(Elf32_Shdr) * ehdr.e_shstrndx, SEEK_SET); //定位section header if(read(fd, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)){ printf("Read Section string table failed!"); goto _error; } printf("Read Section string table success!\n"); if((shstr = (char *)malloc(shdr.sh_size)) == NULL){ printf("malloc space for section string table failed!"); goto _error; } lseek(fd, shdr.sh_offset, SEEK_SET); //定位string table的位置 if(read(fd, shstr, shdr.sh_size) != shdr.sh_size){ printf("Read string table failed!"); goto _error; } printf("Read string table success!\n"); lseek(fd, ehdr.e_shoff, SEEK_SET); for(i = 0; i < ehdr.e_shnum; i++){ if(read(fd, &shdr, sizeof(Elf32_Shdr)) != sizeof(Elf32_Shdr)){ printf("Find section .textprocedure failed!"); goto _error; } if(strcmp(shstr + shdr.sh_name, section_name) == 0) { base = shdr.sh_offset; length = shdr.sh_size; printf("Find section %s \n", section_name); break; } } lseek(fd, base, SEEK_SET); content = (char*)malloc(length); if(content == NULL){ printf("malloc space for content failed!"); goto _error; } if(read(fd, content, length) != length){ printf("Read section .text dailed!"); goto _error; } printf("Read section .text success!\n"); nblock = length / block_size; nsize = base / 4096 + (base % 4096 == 0 ? 0 : 1); printf("base = %d, length = %d\n", base, length); printf("nblock = %d, nsize = %d\n", nblock, nsize); for(i = 0; i < length; i++){ content[i] = content[i] ^ 6; } lseek(fd, 0, SEEK_SET); if(write(fd, &ehdr, sizeof(Elf32_Ehdr)) != sizeof(Elf32_Ehdr)){ printf("Write Elf header to so failed!\n"); goto _error; } lseek(fd, base, SEEK_SET); if(write(fd, content, length) != length){ printf("Write modified content to so failed!"); goto _error; } printf("Write modified content to so success!\n"); printf("Encrypt Completed!\n"); _error: close(fd); free(content); free(shstr); return 0; } |
1 | gcc -o encry encrypt_section.c |
1 | ./encry libsyc.so |
123456789101112 | lyz@lyz-ubuntu:~/section_test/dec$ gcc -o encry encrypt_section.clyz@lyz-ubuntu:~/section_test/dec$ ./encry libsyc.so open libsyc.so success!Read Elf header success!Read Section string table success!Read string table success!Find section .textsection Read section .text success!base = 8708, length = 24nblock = 1, nsize = 3Write modified content to so success!Encrypt Completed! |
0×3
加密前后对照此section的数据已经被加密了!
0×4
在so文件初始化代码中添加解密函数,解密已经被加密的sectionC++1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 | unsigned long getLibaddr(){ unsigned long ret = 0; char libname[] = "libsyc.so"; char buffer[4096]; char *temp; int pid; FILE *fp; pid = getgid(); sprintf(buffer, "/proc/%d/maps", pid); fp = fopen(buffer, "r"); if(fp == NULL){ LOGV("Open %s failed!", buffer); goto _error; } while(fgets(buffer, sizeof(buffer), fp)){ if(strstr(buffer, libname)){ temp = strtok(buffer, "-"); ret = strtoul(temp, NULL, 16); break; } } _error: fclose(fp); return ret; } void init_getString(){ char name[15]; unsigned int nblock; unsigned int nsize; unsigned long lib_addr; unsigned long text_addr; unsigned int i; Elf32_Ehdr *ehdr; Elf32_Shdr *shdr; lib_addr = getLibaddr(); // LOGV("libaddr is : %d", lib_addr); ehdr = (Elf32_Ehdr *)lib_addr; text_addr = ehdr->e_shoff + lib_addr; nblock = ehdr->e_entry >> 16; nsize = ehdr->e_entry & 0xffff; // LOGV("text_addr is : %d", text_addr); // LOGV("nblock is : %d", nblock); // LOGV("nsize is : %d", nsize); if(mprotect((void*)lib_addr, 4096*nsize, PROT_EXEC | PROT_READ | PROT_WRITE) != 0){ LOGV("mem privilege change failed!"); } LOGV("mem privilege change success!"); for(i = 0; i < nblock; i++){ char *addr = (char *)(text_addr + i); *addr = (*addr) ^ 6; } if(mprotect((void*)lib_addr, 4096*nsize, PROT_EXEC | PROT_READ | PROT_WRITE) != 0){ LOGV("mem privilege change failed!"); } LOGV("mem privilege change success!"); LOGV("testsection decrypt success!"); } |
1 | void init_getString() __attribute__((constructor)); //将解密函数放在初始化代码中 |
0×5
用IDA打开上面生成的so文件定位到init_array段可以看到1 2 3 4 5 6 7 8 9 10 11 12 | init_array:00003E84 ; =========================================================================== .init_array:00003E84 .init_array:00003E84 ; Segment type: Pure data .init_array:00003E84 AREA .init_array, DATA .init_array:00003E84 ; ORG 0x3E84 .init_array:00003E84 DCD _Z14init_getStringv+1 .init_array:00003E88 DCB 0 .init_array:00003E89 DCB 0 .init_array:00003E8A DCB 0 .init_array:00003E8B DCB 0 .init_array:00003E8B ; .init_array ends .init_array:00003E8B |
0×6
到此,对so文件某一section的加密就结束了。0×7
原文地址:http://bbs.pediy.com/showthread.php?t=191649相关文章推荐
- ubuntu 安装后要做的事情
- iOS 手写代码UICollectionView
- coderfoces446c (斐波那契数列)
- SharePoint API测试系列——对Recorded Item做OM操作(委托的妙用)
- iOS-Storyboad动态刷新
- 初探oVirt-小结后重做一遍ovirt环境
- ifconfig 命令用来查看和配置网络设备
- Android笔记:获取url或uri字符串中的参数值
- 第四例:Intent启动Activity的几种方式(一)
- NYOJ 数字分隔(二)
- IOS 开发学习(3): IOS UI架构设计
- 如何将计算机加入到域环境中
- 应对Memcached缓存失效,导致高并发查询DB的几种思路
- 配置Snappy压缩
- 如何对网页的加载进行性能优化
- javaEE7中websocket的一个小问题
- kvo深入浅出举例
- MacTex XeLaTex xdvipdfmx:fatal: pdf_ref_obj(): passed invalid object. 报错的解决方法
- JS-获取图片地址
- iOS-Storyboad动态刷新