二进制修改程序改初始化数据

给我修改个初始化参数吧

有天公司硬件找到我,要我给他修改一个功放初始化参数,调试效果。

找到功放驱动源码,功放初始化参数是写在一个二维数组,地址和数据一一对应,在系统初始化过程,一个个写进功放。

在他看来需求很简单,改一个寄存器的初始化值然后编译输出一个临时软件给他验证。

可是,这套代码很庞大,编译非常耗时,而且还要考虑版本匹配等问题,好吧,得动点歪主意了。

认识 nm 命令

只是改个数字,直接二进制修改即可吧,拿到硬件机器的可执行文件直接修改完再放回去就好嘛。

但这需要知道这部分数据放在可执行文件的什么地方,想起 nm 命令和可以查看可执行文件的符号信息。

回顾一下 nm 命令:

nm 命令可以读出可执行对象的符号表及符号类型、符号的值。

常用的参数如下

  • -a :显示所有符号;
  • -C : 使 C++ 函数名更具可读性。

符号类型说明:

对于每个符号来说,如果符号类型是小写的,则表示该符号是 local 的;大写则表明该符号是 globle(external)的。

  • A :表示该符号是绝对的,不允许改变,如中断向量表;
  • B :表示该符号出现在非初始化数据段(bss)中;
  • D :表示该符号位于初始化数据段中;
  • R :表示该符号位于只读数据区;
  • U :表示该符号在当前文件中是未定义的,即改符号出现在别的文件中。

其中关于符号值的说法,在程序运行时应当是指的是在内存中地址,而这个符号值的地址和它在文件中的地址是否对应的上呢,我想它应该和程序加载地址有关,这里我没去深究它,这个值和它在文件中的地址还是对的上的。

一个例子

上码:

#include <stdio.h>
#include <stdint.h>

char              data_1[] = "hello";
static char       data_2[] = "world";
const static char data_3[] = "!!!";

int main(int argc, char *argv[])
{
	printf("%s %s%s\r\n", data_1, data_2, data_3);

	printf("0x%x 0x%x 0x%x\r\n", data_1, &data_2, &data_3);

	printf("%s\r\n", (char*)0x601038);

	return 0x00;
}

其中第一个 printf 打印他们的值,等下我们会使用二进制的方式来修改它;

第二个 printf 打印的是他们的地址;

第三个 printf 是打印 0x601038 地址的值,这里我提前用 nm 知道这个地址是 data_1 的。

使用 gcc 编译输出二进制 main,然后执行 nm main 后输出如下(只截取了部分):

0000000000601044 B __bss_start
0000000000601044 b completed.7594
0000000000601038 D data_1
000000000060103e d data_2
0000000000400614 r data_3
0000000000601028 D __data_start
0000000000601028 W data_start
............................
0000000000400526 T main
                 U printf@@GLIBC_2.2.5
00000000004004a0 t register_tm_clones
0000000000400430 T _start

执行 main 输出如下:

hello world!!!
0x601038 0x60103e 0x400614
hello

修改试试看

让我们试试修改 !!! 为 ???,首先我们得有个好的 bin 档编辑器,这里推荐使用 HxD Hex Editor,打开后我们试试 0x400614 这个地址,发现找不到,让我们再试试 0x614 这个地址,发现找到了 !!! 如下图:

这里前面的 60 和 40 究竟是怎么来的,我还没查到,让我们先来把它修改成 ??? 吧,如下图:

保存一下,然后再执行 main 发现输出变成了如下:

hello world???
0x601038 0x60103e 0x400614
hello

是不是很有趣 _

扫码关注我了解更多,元旦假期愉快! _

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值