您的位置:首页 > 其它

加密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的代码:

123JNIEXPORT 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;

}

编译

1gcc -o encry encrypt_section.c
执行加密

1

./encry
libsyc.so

结果:

123456789101112lyz@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!");

}

将init_getstring函数加入init_array段中~

1void 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: