【问题标题】:How to interpret a dump of binary file?如何解释二进制文件的转储?
【发布时间】:2018-10-28 09:59:59
【问题描述】:

考虑二进制文件 (amd64) 转储的以下输出部分:

$ objdump -D /lib/modules/4.16.0-1-amd64/kernel/drivers/usb/class/cdc-acm.ko
...
25f0:       e8 00 00 00 00          callq  25f5 <acm_port_dtr_rts+0x5>
25f5:       53                      push   %rbx
25f6:       48 89 fb                mov    %rdi,%rbx
25f9:       48 83 ef 20             sub    $0x20,%rdi
25fd:       85 f6                   test   %esi,%esi
25ff:       74 3c                   je     263d <acm_port_dtr_rts+0x4d>
2601:       b8 03 00 00 00          mov    $0x3,%eax
2606:       b9 03 00 00 00          mov    $0x3,%ecx
260b:       f6 83 60 08 00 00 40    testb  $0x40,0x860(%rbx)
2612:       89 83 94 07 00 00       mov    %eax,0x794(%rbx)
2618:       75 18                   jne    2632 <acm_port_dtr_rts+0x42>
261a:       48 8d 73 e8             lea    -0x18(%rbx),%rsi
261e:       45 31 c9                xor    %r9d,%r9d
2621:       45 31 c0                xor    %r8d,%r8d
2624:       ba 22 00 00 00          mov    $0x22,%edx
2629:       e8 32 eb ff ff          callq  1160 <acm_ctrl_msg.isra.10>
262e:       85 c0                   test   %eax,%eax
2630:       74 09                   je     263b <acm_port_dtr_rts+0x4b>
2632:       f6 83 1c 08 00 00 02    testb  $0x2,0x81c(%rbx)
2639:       75 08                   jne    2643 <acm_port_dtr_rts+0x53>
263b:       5b                      pop    %rbx
263c:       c3                      retq
263d:       89 f1                   mov    %esi,%ecx
263f:       31 c0                   xor    %eax,%eax
2641:       eb c8                   jmp    260b <acm_port_dtr_rts+0x1b>
2643:       48 8b 7b e8             mov    -0x18(%rbx),%rdi
2647:       48 c7 c6 00 00 00 00    mov    $0x0,%rsi
264e:       5b                      pop    %rbx
264f:       48 83 c7 30             add    $0x30,%rdi
2653:       e9 00 00 00 00          jmpq   2658 <acm_port_dtr_rts+0x68>
2658:       0f 1f 84 00 00 00 00    nopl   0x0(%rax,%rax,1)
265f:       00
...

cdc-acm.c 的以下部分对应于上面的转储:

static void acm_port_dtr_rts(struct tty_port *port, int raise)
{
  struct acm *acm = container_of(port, struct acm, port);
  int val;
  int res;

  if (raise)
        val = ACM_CTRL_DTR | ACM_CTRL_RTS;
  else
        val = 0;

  acm->ctrlout = val;

  res = acm_set_control(acm, val);
  if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE))
        dev_err(&acm->control->dev, "failed to set dtr/rts\n");
}

此外,这里使用了以下常量:

#define ACM_CTRL_DTR            0x01
#define ACM_CTRL_RTS            0x02

如何从源代码中找出转储中的哪一行对应于以下行?

val = ACM_CTRL_DTR | ACM_CTRL_RTS;

编辑

以下过程用于更改二进制文件:

hexdump -v -e "1/1 \" %02x\n\"" cdc-acm.ko.orig >text_file
<edit text_file>
xxd -r -p text_file cdc-acm.ko

【问题讨论】:

  • 在 csc-acm.h ACM_CTRL_DTR 是 0x01 和 ACM_CTRL_RTS 是 0x02 。 0x01 | 0x02 = 0x03。编译器将此计算为编译时优化。

标签: assembly x86-64 reverse-engineering objdump


【解决方案1】:

如果您使用调试信息进行编译,则 objdump -d -S 将源代码行与 asm 交错。 gdb 可以使用外部调试符号(例如来自 linux-image-4.16.0-1-amd64-dbg),但我认为这对于反汇编内核模块没有用处。

我不知道如何告诉objdump 寻找/使用它们。有关单独调试信息的更多信息,请参阅 https://www.technovelty.org/code/separate-debug-info.html,但它没有说明 objdump -S 使用它们,只有 gdb。


否则,ACM_CTRL_DTR | ACM_CTRL_RTS0x3,当 %esi 为零时,有一个 test/je 会跳过一对 mov $3, %eax / mov $3, %ecx 指令,所以这是 if(raise) 分支。第二个整数函数 arg 在 x86-64 System V 调用约定中的 RSI/ESI 中传递,所以它是 raise,除非它被早期的 call 或你用 ... 隐藏的其他东西破坏了。

这两个mov 指令可能通过将val 分配给其他东西来解释,但我没有尝试完全遵循逻辑。

【讨论】:

  • raise 来自函数参数 - 我已将其添加到 OP。此外,Debian linux-image-4.16.0-1-amd64-dbg 中有以下调试包。是否可以使用它,如果可以,如何使用?最终目标是在不重新编译整个内核的情况下将该值更改为 0
  • @IgorLiferenko:我不确定是否可以通过objdump -d -S 使用外部调试符号。
  • @IgorLiferenko 在我看来就像将 25fd: 85 f6 test %esi,%esi 更改为 31 f6 xorl %esi,%esi 会达到您想要的效果,但是从 C 源代码编译后修改机器代码总是很脆弱,因为下次在进行一些细微的源代码更改后(即使在该源文件的不同部分或包含的某些头文件中)编译器可能会产生相当不同的机器代码,因此您可能会重新考虑如何在构建之前在源代码中调整它(或如何快速构建)。或者至少检测周围更广泛的操作码,所以只有当代码“像这样”时你才会修补它。
  • @IgorLiferenko 提出的补丁就像将if (raise) 更改为if (raise=0)(这不是错字,它是if 表达式中的赋值)。
  • @Ped7g 我尝试在两个地方简单地将03 更改为00,并且效果很好。请参阅 OP 中的 EDIT。我还没有尝试你的变种。你认为我的解决方案是好的,还是你的更好?附言我使用本地机器进行测试 - 我可以毫无问题地在 Debian 中重新编译内核 - 在我有很多 openwrt 设备(我很少更新)上,这个 hack 的主要用途是必要的,我使用图像生成器生成固件它们(从源代码编译太麻烦了)。所以,二进制补丁是一个很好的解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2018-03-23
  • 1970-01-01
相关资源
最近更新 更多