-
-
[分享][原创]修改android app_process elf (实现rrrfff大神 <android全局注入>第一步)
-
发表于:
2018-1-25 23:11
12858
-
[分享][原创]修改android app_process elf (实现rrrfff大神 <android全局注入>第一步)
好久没注意我自己留的坑,所以,看到有人回复想要镜像,于是根据这段时间看android/linker源码的内容,写了一个简单的自动化修改app_process工具,运行过之后返回的so的名字,就是最终你注入的so的名字。
tag 为debug的被修改为了我们自己注入的so的名字
更新
好久没注意我自己留的坑,所以,看到有人回复想要镜像,于是根据这段时间看android/linker源码的内容,写了一个简单的自动化修改app_process工具,运行过之后返回的so的名字,就是最终你注入的so的名字。
tag 为debug的被修改为了我们自己注入的so的名字
我是一名做android安全的新手,最近在论坛里看到
@rrrfff大神发的博文
一种简单的Android全局注入方案 很受启发,准备结合着xposed学习一下。没想到第一步就遇到了阻碍^_^。不知道论坛里的各位大佬是怎么修改elf的,我的方案是手动寻找到dyn表的位置,然后打印出来tag和value值,再把映射的值放到程序里去写入到app_process中。以下是我个人的思路:
第一步找到dyn在app_process文件中的偏移位置:
看显示内容:
yougar@ubuntu:~/Programs/so_injection/os$ readelf -d app_process
Dynamic section at offset 0x3dc0 contains 32 entries: ## offset
Tag Type Name/Value
0x00000003 (PLTGOT) 0x4f0c
0x00000002 (PLTRELSZ) 440 (bytes)
0x00000017 (JMPREL) 0xe74
0x00000014 (PLTREL) REL
0x00000011 (REL) 0xdb4
0x00000012 (RELSZ) 192 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 21
0x00000015 (DUBUG) 0x0
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x598
0x0000000a (STRSZ) 1521 (bytes)
0x00000004 (HASH) 0xb8c
0x00000001 (NEEDED) Shared library: [libandroid_runtime.so]
0x00000001 (NEEDED) Shared library: [libbinder.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libcutils.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libutils.so]
0x00000020 (PREINIT_ARRAY) 0x4d40
0x00000021 (PREINIT_ARRAYSZ) 0x8
0x00000019 (INIT_ARRAY) 0x4d48
0x0000001b (INIT_ARRAYSZ) 12 (bytes)
0x0000001a (FINI_ARRAY) 0x4d54
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x0000001e (FLAGS) BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x00000000 (NULL) 0x0
发现偏移位置为0x3dc0,转换为10进制是15808
第二步结合<elf.h>打印出d_tag为0x00000001,第一个tag类型为needed的d_val,源码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 3) {
printf("usage:%s <file> <offset>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDONLY);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn); // 单个dyn在文件中所占大小
offset += 14 * len; // 由于第一个出现needed类型的tag在tag数组里的偏移是14,所以这里设置偏移长度+14 * len
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
read(f_id, elf32_dyn, len);
printf("Tag: %u, Val: %u\n", elf32_dyn -> d_tag, elf32_dyn -> d_un.d_val);
}
运行之,打印结果:
这里的这个val对应的是字符表的字符偏移,去掉lib占的内存,那么我的程序应该设置的val大小为1416
第三步修改tag和val,代码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 4) {
printf("usage:%s <file> <offset> <value>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
value = parse_long(argv[3]);
if(value == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDWR);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn);
offset += 8 * len; // 要修改的dyn在数组中的偏移位置是8
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
elf32_dyn -> d_tag = DT_NEEDED;
elf32_dyn -> d_un.d_val = value;
write(f_id, elf32_dyn, len);
}
到这里修改操作全部完成。查看结果:
有一点我的方案跟rrrfff大神的不太一样,就是我是直接把修改过的app_process push到模拟器里面的,没有改虚拟机文件。在这一步,我还遇到了一点小问题,不过,google之后,还是顺利解决了。这里我还是分享一下吧,作为备忘录。
问题如下:
adb push C:\***\app_process /system/bin之后,报read-only file system错误。这个我早想到过,于是按照有人提出的解决方法mount -o remount,rw /system,发现运行过这个命令之后,竟然报相同的错误。这一解决方案被很多人采纳了,可为啥我的就不行。后来又看到一个相似的提问的回答,然后成功解决了我的问题。回答是:启动模拟器的命令参数要有-writable-system才可以写/system文件夹。
看显示内容:
yougar@ubuntu:~/Programs/so_injection/os$ readelf -d app_process
Dynamic section at offset 0x3dc0 contains 32 entries: ## offset
Tag Type Name/Value
0x00000003 (PLTGOT) 0x4f0c
0x00000002 (PLTRELSZ) 440 (bytes)
0x00000017 (JMPREL) 0xe74
0x00000014 (PLTREL) REL
0x00000011 (REL) 0xdb4
0x00000012 (RELSZ) 192 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 21
0x00000015 (DUBUG) 0x0
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x598
0x0000000a (STRSZ) 1521 (bytes)
0x00000004 (HASH) 0xb8c
0x00000001 (NEEDED) Shared library: [libandroid_runtime.so]
0x00000001 (NEEDED) Shared library: [libbinder.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libcutils.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libutils.so]
0x00000020 (PREINIT_ARRAY) 0x4d40
0x00000021 (PREINIT_ARRAYSZ) 0x8
0x00000019 (INIT_ARRAY) 0x4d48
0x0000001b (INIT_ARRAYSZ) 12 (bytes)
0x0000001a (FINI_ARRAY) 0x4d54
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x0000001e (FLAGS) BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x00000000 (NULL) 0x0
发现偏移位置为0x3dc0,转换为10进制是15808
第二步结合<elf.h>打印出d_tag为0x00000001,第一个tag类型为needed的d_val,源码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 3) {
printf("usage:%s <file> <offset>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDONLY);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn); // 单个dyn在文件中所占大小
offset += 14 * len; // 由于第一个出现needed类型的tag在tag数组里的偏移是14,所以这里设置偏移长度+14 * len
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
read(f_id, elf32_dyn, len);
printf("Tag: %u, Val: %u\n", elf32_dyn -> d_tag, elf32_dyn -> d_un.d_val);
}
运行之,打印结果:
这里的这个val对应的是字符表的字符偏移,去掉lib占的内存,那么我的程序应该设置的val大小为1416
第三步修改tag和val,代码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 4) {
printf("usage:%s <file> <offset> <value>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
value = parse_long(argv[3]);
if(value == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDWR);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn);
offset += 8 * len; // 要修改的dyn在数组中的偏移位置是8
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
elf32_dyn -> d_tag = DT_NEEDED;
elf32_dyn -> d_un.d_val = value;
write(f_id, elf32_dyn, len);
}
到这里修改操作全部完成。查看结果:
有一点我的方案跟rrrfff大神的不太一样,就是我是直接把修改过的app_process push到模拟器里面的,没有改虚拟机文件。在这一步,我还遇到了一点小问题,不过,google之后,还是顺利解决了。这里我还是分享一下吧,作为备忘录。
问题如下:
adb push C:\***\app_process /system/bin之后,报read-only file system错误。这个我早想到过,于是按照有人提出的解决方法mount -o remount,rw /system,发现运行过这个命令之后,竟然报相同的错误。这一解决方案被很多人采纳了,可为啥我的就不行。后来又看到一个相似的提问的回答,然后成功解决了我的问题。回答是:启动模拟器的命令参数要有-writable-system才可以写/system文件夹。
yougar@ubuntu:~/Programs/so_injection/os$ readelf -d app_process
Dynamic section at offset 0x3dc0 contains 32 entries: ## offset
Tag Type Name/Value
0x00000003 (PLTGOT) 0x4f0c
0x00000002 (PLTRELSZ) 440 (bytes)
0x00000017 (JMPREL) 0xe74
0x00000014 (PLTREL) REL
0x00000011 (REL) 0xdb4
0x00000012 (RELSZ) 192 (bytes)
0x00000013 (RELENT) 8 (bytes)
0x6ffffffa (RELCOUNT) 21
0x00000015 (DUBUG) 0x0
0x00000006 (SYMTAB) 0x148
0x0000000b (SYMENT) 16 (bytes)
0x00000005 (STRTAB) 0x598
0x0000000a (STRSZ) 1521 (bytes)
0x00000004 (HASH) 0xb8c
0x00000001 (NEEDED) Shared library: [libandroid_runtime.so]
0x00000001 (NEEDED) Shared library: [libbinder.so]
0x00000001 (NEEDED) Shared library: [libc.so]
0x00000001 (NEEDED) Shared library: [libcutils.so]
0x00000001 (NEEDED) Shared library: [libdl.so]
0x00000001 (NEEDED) Shared library: [liblog.so]
0x00000001 (NEEDED) Shared library: [libm.so]
0x00000001 (NEEDED) Shared library: [libstdc++.so]
0x00000001 (NEEDED) Shared library: [libutils.so]
0x00000020 (PREINIT_ARRAY) 0x4d40
0x00000021 (PREINIT_ARRAYSZ) 0x8
0x00000019 (INIT_ARRAY) 0x4d48
0x0000001b (INIT_ARRAYSZ) 12 (bytes)
0x0000001a (FINI_ARRAY) 0x4d54
0x0000001c (FINI_ARRAYSZ) 8 (bytes)
0x0000001e (FLAGS) BIND_NOW
0x6ffffffb (FLAGS_1) Flags: NOW
0x00000000 (NULL) 0x0
发现偏移位置为0x3dc0,转换为10进制是15808
第二步结合<elf.h>打印出d_tag为0x00000001,第一个tag类型为needed的d_val,源码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 3) {
printf("usage:%s <file> <offset>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDONLY);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn); // 单个dyn在文件中所占大小
offset += 14 * len; // 由于第一个出现needed类型的tag在tag数组里的偏移是14,所以这里设置偏移长度+14 * len
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
read(f_id, elf32_dyn, len);
printf("Tag: %u, Val: %u\n", elf32_dyn -> d_tag, elf32_dyn -> d_un.d_val);
}
运行之,打印结果:
这里的这个val对应的是字符表的字符偏移,去掉lib占的内存,那么我的程序应该设置的val大小为1416
第三步修改tag和val,代码如下:
#include <stdio.h>
#include <elf.h>
#include <unistd.h>
#include <fcntl.h>
#include <error.h>
#include <errno.h>
#include <stdlib.h>
long parse_long(const char * v) {
long off;
off = atol(v);
if(off == 0) {
if(errno != 0) {
error(201, errno, "parse offset <%s> to unsigned long", v);
return -1;
}
}
return off;
}
int main(int argc, const char **argv) {
if(argc != 4) {
printf("usage:%s <file> <offset> <value>\n", argv[0]);
return -1;
}
off_t offset, current, value;
offset = parse_long(argv[2]);
if(offset == -1) {
return -1;
}
value = parse_long(argv[3]);
if(value == -1) {
return -1;
}
int f_id;
f_id = open(argv[1], O_RDWR);
if (f_id == -1) {
error(201, errno, "open %s;", argv[1]);
return -1;
}
size_t len = sizeof(Elf32_Dyn);
offset += 8 * len; // 要修改的dyn在数组中的偏移位置是8
current = lseek(f_id, offset, SEEK_SET);
if(current == -1) {
error(201, errno, "lseek file with offset %ld", offset);
return -1;
}
if(current != offset) {
printf("file %s current pos <%ld> not equal to offset <%ld>\n", argv[1], current, offset);
return -1;
}
Elf32_Dyn *elf32_dyn = (Elf32_Dyn*)malloc(len);
elf32_dyn -> d_tag = DT_NEEDED;
elf32_dyn -> d_un.d_val = value;
write(f_id, elf32_dyn, len);
}
到这里修改操作全部完成。查看结果:
有一点我的方案跟rrrfff大神的不太一样,就是我是直接把修改过的app_process push到模拟器里面的,没有改虚拟机文件。在这一步,我还遇到了一点小问题,不过,google之后,还是顺利解决了。这里我还是分享一下吧,作为备忘录。
问题如下:
adb push C:\***\app_process /system/bin之后,报read-only file system错误。这个我早想到过,于是按照有人提出的解决方法mount -o remount,rw /system,发现运行过这个命令之后,竟然报相同的错误。这一解决方案被很多人采纳了,可为啥我的就不行。后来又看到一个相似的提问的回答,然后成功解决了我的问题。回答是:启动模拟器的命令参数要有-writable-system才可以写/system文件夹。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2018-4-10 16:13
被Yougar编辑
,原因: 提供一个自动化工具