#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文件夹。