加密SO文件中自定义的section

加密SO文件中自定义的section

作者: 0n1y3nd丶  分类: Android  发布时间: 2014-08-29 18:22  ė  6暂无评论
前言

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

0×1

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

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

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

System.out.println(returnString());

生成libsyc.so









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
//SO---------------加密----------------------
 
#include <sys/types.h>
#include <elf.h>
#include <sys/mman.h>
 
//注意上面说解密算法里面的断.mytext就是这里,
//这里把getKey进行了加密,这样对方拿不到你的密钥都没法破解你的dll了
int getKey ( ) __attribute__ ( ( section ( ".mytext" ) ) ) ;
int getKey ( ) {
return 2048 ;
} ;
//这里就是.so初始化的时候,这里进行mytext断的解密工作
void init_getKey ( ) __attribute__ ( ( constructor ) ) ;
unsigned long getLibAddr ( ) ;
 
void init_getKey ( ) {
   char name [ 15 ] ;
   unsigned int nblock ;
   unsigned int nsize ;
   unsigned long base ;
   unsigned long text_addr ;
   unsigned int i ;
   Elf32_Ehdr * ehdr ;
   Elf32_Shdr * shdr ;
  
   base = getLibAddr ( ) ;
  
   ehdr = ( Elf32_Ehdr * ) base ;
   text_addr = ehdr -> e_shoff + base ;
  
   nblock = ehdr -> e_entry >> 16 ;
   nsize = ehdr -> e_entry & 0xffff ;
  
   g_message ( "momo: nblock = %d\n" , nblock ) ;
  
 
   if ( mprotect ( ( void * ) base , 4096 * nsize , PROT_READ | PROT_EXEC | PROT_WRITE ) != 0 ) {
     g_message ( "momo: mem privilege change failed" ) ;
 
   }
   //注意这里就是解密算法, 要和加密算法完全逆向才行不然就解不开了。
   for ( i = 0 ; i < nblock ; i ++ ) {   
     char * addr = ( char * ) ( text_addr + i ) ;
     * addr = ~ ( * addr ) ;
   }
  
   if ( mprotect ( ( void * ) base , 4096 * nsize , PROT_READ | PROT_EXEC ) != 0 ) {
     g_message ( "momo: mem privilege change failed" ) ;
   }
   g_message ( "momo: Decrypt success" ) ;
}
 
unsigned long getLibAddr ( ) {
   unsigned long ret = 0 ;
   char name [ ] = "libmono.so" ;
   char buf [ 4096 ] , * temp ;
   int pid ;
   FILE * fp ;
   pid = getpid ( ) ;
   sprintf ( buf , "/proc/%d/maps" , pid ) ;
   fp = fopen ( buf , "r" ) ;
   if ( fp == NULL )
   {
     g_message ( "momo: open failed" ) ;
     goto _error ;
   }
   while ( fgets ( buf , sizeof ( buf ) , fp ) ) {
     if ( strstr ( buf , name ) ) {
       temp = strtok ( buf , "-" ) ;
       ret = strtoul ( temp , NULL , 16 ) ;
       break ;
     }
   }
_error :
   fclose ( fp ) ;
   return ret ;
}



0×2

加密代码

加密的流程:

打开so文件,读取elf头部数据,根据e.shoff定位到section header

读取section header的数据,根据sh_offset定位到string table的位置

遍历string table,根据section的名称找到需要加密的section

找到之后,根据sh_offset和sh_size读取section里的数据到变量中

加密

加密之后的数据覆盖原位置的数据

编译

执行加密

结果:

 0×3

加密前后对照

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

0×4

在so文件初始化代码中添加解密函数,解密已经被加密的section

将init_getstring函数加入init_array段中~

生成包含解密代码的so。

0×5

用IDA打开上面生成的so文件

定位到init_array段可以看到

进入init_getString函数

0×6

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

0×7

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

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
//SO---------------加密----------------------
 
#include <sys/types.h>
#include <elf.h>
#include <sys/mman.h>
 
//注意上面说解密算法里面的断.mytext就是这里,
//这里把getKey进行了加密,这样对方拿不到你的密钥都没法破解你的dll了
int getKey ( ) __attribute__ ( ( section ( ".mytext" ) ) ) ;
int getKey ( ) {
return 2048 ;
} ;
//这里就是.so初始化的时候,这里进行mytext断的解密工作
void init_getKey ( ) __attribute__ ( ( constructor ) ) ;
unsigned long getLibAddr ( ) ;
 
void init_getKey ( ) {
   char name [ 15 ] ;
   unsigned int nblock ;
   unsigned int nsize ;
   unsigned long base ;
   unsigned long text_addr ;
   unsigned int i ;
   Elf32_Ehdr * ehdr ;
   Elf32_Shdr * shdr ;
  
   base = getLibAddr ( ) ;
  
   ehdr = ( Elf32_Ehdr * ) base ;
   text_addr = ehdr -> e_shoff + base ;
  
   nblock = ehdr -> e_entry >> 16 ;
   nsize = ehdr -> e_entry & 0xffff ;
  
   g_message ( "momo: nblock = %d\n" , nblock ) ;
  
 
   if ( mprotect ( ( void * ) base , 4096 * nsize , PROT_READ | PROT_EXEC | PROT_WRITE ) != 0 ) {
     g_message ( "momo: mem privilege change failed" ) ;
 
   }
   //注意这里就是解密算法, 要和加密算法完全逆向才行不然就解不开了。
   for ( i = 0 ; i < nblock ; i ++ ) {   
     char * addr = ( char * ) ( text_addr + i ) ;
     * addr = ~ ( * addr ) ;
   }
  
   if ( mprotect ( ( void * ) base , 4096 * nsize , PROT_READ | PROT_EXEC ) != 0 ) {
     g_message ( "momo: mem privilege change failed" ) ;
   }
   g_message ( "momo: Decrypt success" ) ;
}
 
unsigned long getLibAddr ( ) {
   unsigned long ret = 0 ;
   char name [ ] = "libmono.so" ;
   char buf [ 4096 ] , * temp ;
   int pid ;
   FILE * fp ;
   pid = getpid ( ) ;
   sprintf ( buf , "/proc/%d/maps" , pid ) ;
   fp = fopen ( buf , "r" ) ;
   if ( fp == NULL )
   {
     g_message ( "momo: open failed" ) ;
     goto _error ;
   }
   while ( fgets ( buf , sizeof ( buf ) , fp ) ) {
     if ( strstr ( buf , name ) ) {
       temp = strtok ( buf , "-" ) ;
       ret = strtoul ( temp , NULL , 16 ) ;
       break ;
     }
   }
_error :
   fclose ( fp ) ;
   return ret ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值