http://0nly3nd.sinaapp.com/?p=695
前言
加密已知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里的数据到变量中
加密
加密之后的数据覆盖原位置的数据
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
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