加密SO文件中自定义的section

2023-11-07

加密SO文件中自定义的section

作者: 0n1y3nd丶  分类: Android  发布时间: 2014-08-29 18:22  ė  61条评论

前言

加密已知so文件中的某一section,在运行时解密。执行里面的代码!

0×1

libsyc.so里有一个.textsection,里面有一个方法返回一个字符串!

生成未加密的libsyc.so的代码:

1
2
3
JNIEXPORT jstring returnString ( JNIEnv* env , jclass cls ) {
     return env -> NewStringUTF ( "String From Native!" ) ;
}

然后java代码中调用returnString这个方法

System.out.println(returnString());

生成libsyc.so

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

结果:

1
2
3
4
5
6
7
8
9
10
11
12
lyz @ lyz - ubuntu : ~ / section_test / dec $ gcc - o encry encrypt_section . c
lyz @ 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 = 24
nblock = 1 , nsize = 3
Write modified content to so success !
Encrypt Completed !

 0×3

加密前后对照

此section的数据已经被加密了!

0×4

在so文件初始化代码中添加解密函数,解密已经被加密的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
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!" ) ;
}

将init_getstring函数加入init_array段中~

1
void init_getString ( ) __attribute__ ( ( constructor ) ) ; //将解密函数放在初始化代码中

生成包含解密代码的so。

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

进入init_getString函数

0×6

到此,对so文件某一section的加密就结束了。

0×7

原文地址:http://bbs.pediy.com/showthread.php?t=191649

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

加密SO文件中自定义的section 的相关文章

  • GUI编程—PyQt5学习笔记1

    GUI 图形用户界面 Graphical User Interface 简称 GUI 又称图形用户接口 是指采用图形方式显示的计算机操作用户界面 PyQt5常用模块 QtWidgets 包含了一整套UI元素控件 用于建立符合系统风格的界面
  • 启动mysql服务报错:mysql服务无法启动

    一 问题描述 之前mysql服务好好的 突然无法启动了 win10系统 64位 mysql8 0 23 二 问题解决 1 mysqld console命令查看具体报错 C WINDOWS system32 gt mysqld console

随机推荐

  • C++ 2:new和delete,volatile关键字,auto关键字,基于范围for循环,string简单使用

    文章目录 1 B Tree 的结构设计 2 new和delete 2 1 new的三种用法 2 2 对于内置类型new delete malloc free 可以混用 3 C11的新特性 3 1 类型推导 3 2 auto的推导规则 3 2
  • geeksforgeeks —— 算法 1

    目录 算法 一 查找和排序 1 1 线性查找 1 2 二分查找 1 3 跳跃搜索 1 4 插值搜索 1 5 指数搜索 1 6 为什么二元搜索优于三元搜索 1 7 选择排序 1 8 冒泡排序 1 9 插入排序 1 10 归并排序 1 11 堆
  • 关于指针大小(c语言)

    32位系统默认指针大小为4个字节 8位为一个字节 因为32位系统默认的内存寻址空间是4G 所以指针大小为4个字节可以完成对4G空间的寻址 2 32约为4个G 64位系统默认指针大小为8个字节 理论上寻址空间可达到1800万个TB 指针大小为
  • git给服务器传文件在哪里,git上传文件服务器地址

    git上传文件服务器地址 内容精选 换一换 在本地主机和Windows弹性云服务器上分别安装QQ exe等工具进行数据传输 使用远程桌面连接mstsc方式进行数据传输 该方式不支持断点续传 可能存在传输中断的情况 因此不建议上传大文件 文件
  • qt怎么一个程序显示两个窗口

    首先我们要把 ui文件的QMainWindow改成QDialog 用记事本 然后把 ui对应的头文件和 cpp 出现QMainWindow改成QDialog 如图重点其包含头文件定义也记得修改 然后非模态显示 才不堵塞主窗口 然后在主窗口程
  • 星际2正在等待暴雪服务器的响应,win7系统玩星际2一直停留在"正在更新暴雪启动器"页面的解决方法...

    很多小伙伴都遇到过win7系统玩星际2一直停留在 正在更新暴雪启动器 页面的困惑吧 一些朋友看过网上零散的win7系统玩星际2一直停留在 正在更新暴雪启动器 页面的处理方法 并没有完完全全明白win7系统玩星际2一直停留在 正在更新暴雪启动
  • 【交叉二五码及其校验码计算方式】

    一 交叉二五码 交叉二五码是1972年美国Intermec公司发明的一种条 空均表示信息的连续型 非定长 具有自校验功能的双向条码 它的字符集为数字字符0 9 交叉二五条码由左侧空白区 起始符 数据符 终止符及右侧空白区构成 它的每一个条码
  • CentOS 7虚拟机安装常用软件

    依然是虚拟机安装常用软件系列 CentOS 7目前官方支持到2024 还行 1 VMWare 安装CentOS 7 默认都安装成功了 2 换源 更新 阿里源最近老是403 换了网易源 sudo wget O etc yum repos d
  • python对字符串中指定字符进行替换

    1 替换指定的所有字符 string replace a b 表示将字符串string中所有字符为a的替换为b 例子 string abcabcabc string string replace a b print string 输出 bb
  • SpringBoot默认Json框架Jackson解析-基础篇

    1 Springboot返回JSON数据的方式 目前SpringBoot提供的Json格式有三种 Jackson 默认 Gson JsonB 我们都可以在springboot自动配置模块spring boot autoconfigure中查
  • (深度/广度优先算法)——遍历邻接表(C语言)

    一 算法代码 采用邻接表表示图的遍历 include
  • 基于同一IP的不同端口访问不同的网站

    目录 创建网站目录 一 ip 端口1的根目录 二 ip 端口2的根目录 编写虚拟主机配置文件 配置完成 实验结果测试 创建网站目录 一 ip 端口1的根目录 这个目录大家可以随意 配置文件里同步即可 mkdir p www port 909
  • 嵌入式系统:中断

    中断 一 查询与中断 1 查询 按照主函数中的语句顺序 顺序执行 1 优点 结构简单 易于理解 2 缺点 无法充分利用CPU资源 2 中断 程序顺序执行 遇到中断使能 跳转执行中断函数 1 优点 充分利用CPU资源 提高效率 易于处理突发事
  • 微信小程序里面如何使用svg图片

    首先准备一段svg代码如下
  • 查找随机数组中的质数个数

    看到这个标题 我们首先要想到几个问题来仔细分析 1 随机数如何生成 2 质数是为何物 下面我们就来一一解决刚刚想到的问题 1 随机数 我们假设想生成1000以内的21个随机数 Dim i As Integer x As Integer Ra
  • 【financial markets】 2. EURIBOR

    1 EURIBOR EURIBOR 全称是 EURO Interbank offered rate 相当于 欧元的LIBOR 与EONIA一样 EURIBOR是无担保的银行间借贷利率 但是有两点很明显的不同 1 EURIBOR的也是取平均数
  • Docker搭建FastDFS

    Docker搭建FastDFS 1 搜索镜像 docker search fastdfs root localhost data docker search fastdfs NAME DESCRIPTION STARS OFFICIAL A
  • java 定时任务之一 @Scheduled注解(第一种方法)

    本文仅供参考 使用spring Scheduled注解执行定时任务 步骤 1 xmlns 添加 http www springframework org schema task http www springframework org sc
  • CentOS下postgres怎么恢复数据库.bak文件_Xtrabackup 实现数据的备份与恢复

    Xtrabackup介绍 Xtrabackup是由percona开源的免费数据库热备份软件 它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞地备份 对于MyISAM的备份同样需要加表锁 mysqldump备份方式是采用的逻辑备份
  • 加密SO文件中自定义的section

    加密SO文件中自定义的section 作者 0n1y3nd丶 分类 Android 发布时间 2014 08 29 18 22 61条评论 前言 加密已知so文件中的某一section 在运行时解密 执行里面的代码 0 1 libsyc s