我想通过使用十六进制编辑器来改变可执行文件中整数声明变量的值,只是假设我知道在代码中声明了一个变量类型int,变量是这样的:
int value = 1337;
我想编辑可执行文件使用十六进制编辑器搜索值1337并将其更改为其他内容,我在ubuntu中尝试ghex但我不知道如何搜索它我将其转换为十六进制但我没有'找到它,先谢谢你们。
答案 0 :(得分:16)
首先,您将使用readelf
来确定变量的虚拟地址(加载程序后它在内存中的位置)。 -s
将显示符号表,我们将grep查找变量的名称。
readelf -s a.out | grep value
这将输出如下所示的行:
64: 000000000060102c 4 OBJECT GLOBAL DEFAULT 24 value
所以这里,文件中的第64个符号是value
。它的加载地址是0x60102c,它的大小是4个字节。现在我们有虚拟地址,但这并没有告诉我们它在文件中的位置。要做到这一点,我们需要做三件事:
让我们再次运行readelf
。 -S
会列出各个部分。
readelf -S a.out
这是输出的片段。请记住,我们变量的地址位于60102c
,我们正在查找60102c
与其Address
之间Address + Size
所在的部分。由于这是一个读写变量,我们可以猜测它将在.data
部分。
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
...
[21] .dynamic DYNAMIC 0000000000600e28 00000e28
00000000000001d0 0000000000000010 WA 6 0 8
[22] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[23] .got.plt PROGBITS 0000000000601000 00001000
0000000000000028 0000000000000008 WA 0 0 8
[24] .data PROGBITS 0000000000601028 00001028
0000000000000008 0000000000000000 WA 0 0 4
[25] .bss NOBITS 0000000000601030 00001030
0000000000000008 0000000000000000 WA 0 0 4
[26] .comment PROGBITS 0000000000000000 00001030
000000000000002c 0000000000000001 MS 0 0 1
果然,.data
在<{1}}到601028
的内存中存在。从此部分的地址中减去601028+8 = 601030
的地址,我们得到:
value
因此, 60102c Address of `value`
- 601028 Start address of .data section
--------
4
距离value
部分的起点偏移4。现在,文件中的.data
部分在哪里?这就是.data
专栏告诉我们的内容。 Offset
从文件偏移.data
开始。知道了这一点,我们就可以找到1028
的文件偏移量:
value
我们已经获得了文件偏移量,现在让我们确保知道会发生什么。您的变量的值为1337.在十六进制中,即0x539。但是,我们需要调出byte order(或“endianness”)。 Intel x86系统是 little endian 。这意味着当一个大于一个字节的整数存储在一个地址时,该值的最重要字节(或“小”端)位于该地址,其余字节位于后续位置(增加地址)。
所以你的1337将被存储(作为一个4字节 1028 File offset of .data section
+ 4 Offset of `value` in .data section
-------
102c File offset of `value`
)在这样的文件中:
int
在“big endian”系统(例如Motorola 68k)上,该值将以相反的顺序显示在文件中:
39 05 00 00
大家都说,如果你在十六进制编辑器中打开你的ELF文件,转到偏移102c,你会看到你的价值:
ELF文件没有校验和或CRC,因此您应该能够在十六进制编辑器中简单地编辑该值,并且在程序执行时它将具有新值!