如何在二进制文件中查找 IDA 的内存地址偏移量



我正在尝试编写一个命令行应用程序,该应用程序可以使用特定地址的十六进制值修改.so文件。

我正在使用 IDA 演示和 HxD 十六进制编辑器

来获取需要更新的地址,但是,每次我尝试修改文件时,无论我使用哪种语言(bash 脚本、php、python)每次编辑文件时,它都会从我从 IDA 和 HxD 十六进制编辑器中获得的错误地址偏移量更新。

我已经看到了一些关于此的帖子,但到目前为止,还没有人能够就如何获得HxD和IDA没有问题找到的地址给出明确的答案:(

在python中,

我使用mmap函数尝试使用以下内容;

import mmap
import contextlib
import os
filesize = os.stat("filetomodify.so").st_size
print int(filesize)

with open("filetomodify.so", 'r+b') as f:
    with contextlib.closing(mmap.mmap(f.fileno(),  access=mmap.ACCESS_WRITE)) as m:
        m[0x173596] = "FF 20"
        m[0x18D88E] = "FF 20"
        m.close()

这使用 os 库来确定作为10025936返回的文件的大小,但是,每次我在 f.fileno()access=mmap.ACCESS_WRITE 之间添加 length=filesize 参数时,我总是会收到一条mmap.error: [Errno 22] Invalid argument错误消息,但是当我省略参数时,我得到一个m: TypeError: Required argument 'length' (pos 2) not found

我使用的 bash 脚本是我在这里找到的,它可以修改文件,但更新了错误的地址;

#!/bin/bash
# param 1: file
# param 2: offset
# param 3: value
# param 4: Size of Bytes
function replaceByte() {
    printf "$(printf '\x%02X' $3)" | dd of="$1" bs=$4 seek=$2 count=1 conv=notrunc &> /dev/null
}
# Usage:
replaceByte 'filetomod.so' "0x173596" "95 E5 0A 2F 66 1E 32 EE 4C B8 9A 6E BD EC 01" 15

如上所述调用函数会更新文件并写入正常,但是当我查找更新的字节字符串(例如,95 E5 0A 2F 66 1E 32 EE 4C B8 9A 6E BD EC 01 - 只是一个您不希望在文件中找到的长唯一字符串)它入到错误的地址, 或者它告诉我偏移量超出了文件大小。

最后,我使用的 php 代码(无论如何我都没想到会取得多大成功)是;

<?php
$fp = fopen('binary_file.bin', 'w+b');
fseek($fp, 173596, );   
fwrite($fp, '95 E5 0A 2F 66 1E 32 EE 4C B8 9A 6E BD EC 01');
fclose($fp);
?>

但是,这不是编辑二进制文件的十六进制值,而是将字符串作为字符串添加到 HxD 地址 0002A61C 的二进制文件中,十六进制代码作为输出的 39 35 20 45 35 20 30 41 20 32 46 20 36 36 20 31 45 20 33 32 20 45 45 20 34 43 20 42 38 20 39 41 20 36 45 20 42 44 20 45 43 20 30 31 95 E5 0A 2F 66 1E 32 EE 4C B8 9A 6E BD EC 01

任何这方面的帮助将不胜感激。我对答案的唯一要求是它可以从命令行运行,无论是 php、bash、python、java 等。

提前谢谢你。

在运行 Centos 6.5 的虚拟机中试用了一些后,我明白了

function replaceByte() {
    printf "$(printf '\x%02X' $3)" |
    dd of="$1" ibs=1 count=1 obs=1 seek="$2" conv=notrunc &> /dev/null
}

问题是seek参数的单位:块,而不是字节。

更改默认块大小时,输入块大小和输出块大小都会更改。因此,seek 参数是指其大小为bs参数值的块。

要解决此问题,您必须像以前一样ibs设置输入块大小,但输出块大小obs必须设置为 1。否则,由于输出是磁盘文件,因此obs值设置为 512 字节(磁盘块大小)。

您可以尝试以下测试来检查输出块的大小是 512,而不是 1:

  1. 创建包含整个空白行(例如 30 个空格)的文本文件 (file.txt)
  2. 检查文件大小是否接近 30 字节。
  3. 运行echo -e 'x41' | dd if=file.txt ibs=1 count=1 seek=3 conv=notrunc(0x41是 A 的 ASCII 代码)
  4. 检查 file.txt 的大小是否已更改:1537 字节(3 个块,每个块 512 字节加上 1 -- 3*512+1)

  5. 由于 file.txt 已"损坏",请重复步骤 1 和 2。

  6. 运行echo -e 'x41' | dd if=file.txt ibs=1 count=1 obs=1 seek=3 conv=notrunc
  7. 检查文件大小.txt是否未更改。
  8. 查看文件的内容并检查是否有"A"替换第 4 个空格。

此致敬意。

P.D:这个功能replaceByte()应该只用一个字节就可以正常工作。如果您需要在一次调用中更改多个连续字节,则必须将printf替换为循环...以及具有适当值的ibs=1

最新更新