修改可执行文件二进制

前言

由于许多程序代码里面包含有一些关键的C函数,大部分C函数的符号都去掉了,随着软件更新,这函数的名称可能发生变化,之前hook这部分函数用的都是动态的方法,就是查找这个函数的模块地址,动态修改二进制。有的时候,上面这种方法就显得比较麻烦了。可能直接静态的修改可执行文件的二进制还要方便快捷

例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int isBrandNew(int i) {
if (i == 0) {
return 1;
}
return 0;
}

int main(int argc, char **argv) {
for (int i = 0; i < 5; i++) {
if (isBrandNew(i)) {
printf("Nice to meet you!\n");
} else {
printf("How about you?\n");
}
}
return 0;
}

上面这个函数利用isBrandNew判断是不是第一次见面,第一次见面就打印Nice to meet you!,否则就打印How about you?

编译执行cc main.c -o main

image-20230118上午83646688

查看并修改二进制

Hopper 查看汇编代码

image-20230118上午84136963

仔细看看这段汇编后的代码

image-20230118上午84828240

黄框里面对应的是i==0为真的逻辑,红框的逻辑其实就是返回值存w0退栈

修改二进制,去掉第一次见面逻辑

这个很简单,把图中loc_100003edc里面的mov w8, #0x1修改为mov w8, #0x0

鼠标点击这一行代码,让编辑光标定位到这一行,然后点击菜单栏的Modify -> Assemble Instruction

image-20230118上午85416756

输入mov w8, #0x0,然后点击Assemble and Go Next

image-20230118上午85847449

最后通过菜单栏File -> Produce New Executable即可,不过这个功能需要许可证,我没有许可证,我们可以看看最后改了哪些16进制

image-20230118上午90014720

可以看到修改后的地方用红框标出来了

修改后的16进制

我们按快捷键撤销修改,看看修改前的16进制

修改前

选中其中20字节,不能选中这一行,因为Hopper显示的是22列,而arm定长指令为4字节,拷贝20字节方便修改

拷贝20字节

同样的方法拷贝修改后的20字节

1
2
3
4
5
# 修改前
E8 0B 40 B9 A8 00 00 35 01 00 00 14 28 00 80 52 E8 0F 00 B9 03 00 00 14 FF 0F 00 B9

# 修改后
E8 0B 40 B9 A8 00 00 35 01 00 00 14 08 00 80 52 E8 0F 00 B9 03 00 00 14 FF 0F 00 B9

用Vim来替换16进制

1
vim -b main # -b表示2进制方式打开

输入%!xxd -g 1 -c 22 -u显示效果匹配Hopper

  • -g 控制每组的字节数
  • -c 控制显示列数
  • -u 用大写显示

image-20230118上午91555963

显示效果如下

image-20230118上午91756971

搜索定位到了

image-20230118上午92445538

发现只匹配了一行,下面用vim的替换功能

1
:%s#40 B9 A8 00 00 35 01 00 00 14 28 00 80 52 E8 0F 00 B9 03 00 00 14#40 B9 A8 00 00 35 01 00 00 14 08 00 80 52 E8 0F 00 B9 03 00 00 14#

image-20230118上午92741650

关键的部分修改成功了,但右边对应的ASCII码还没变,用%!xxd -r写回16进制

但执行不了了,哈哈哈哈😄