我已经在Stack Exchange和其他地方看到了将绕行插入插入已编译代码的参考。我的理解是,本质上是插入了一个jmp指令,然后以某种方式将修补后的程序与包含jmp目标的其他代码链接。 。

#include <stdio.h>

void hello(void) {
    printf("Hello ");
    printf("world!\n");
}

int main(void) {
    hello();
}


假设我只有这个程序编译的二进制文件。尚未采取任何措施以任何方式去除符号或混淆程序。我想插入一个弯路来调用从此函数编译的代码。

#include <stdio.h>

void detour(void) {
    printf("detoured ");
}


补丁程序的输出应为: />您好,绕道世界!


我该怎么办?如何避免在已编译的代码中破坏地址偏移?

我可用的编译器是gcc,clang和icc。我可以使用的操作系统是OS X和Ubuntu。选择您喜欢的答案中的任何一个。

如果此处无法合理回答,则简要概述和一些阅读材料的指针也将是一个很好的答案。 >我知道LD_PRELOAD和ld --wrap。选择该示例是为了使这些方法不容易满足要求。 (当然,您可以将整个hello()函数绕行到显示“ Hello detoured world!”的代码,但是假装您没有源代码并且该函数很简单。)

相关问题

我首先要问如何简单地反汇编和重新汇编已编译的程序,但是有人问过。回应是这非常困难。我的回答是,这不是一件普通的事情。我怀疑我的假设是拆卸和重新组装是绕行的必要步骤,这可能是不正确的。

为什么没有任何反汇编程序可以生成可重新组装的asm代码?

关于StackOverflow的类似问题收到了冷淡的回应。这个问题的重点仅在于插入弯路,而不是一般的“修改”,我认为这里的听众会更容易接受。然后重新组装一个Linux可执行文件

这个逆向工程问题询问有关一般修改二进制文件的问题。提到了许多不同的工具和LD_PRELOAD。一些答案说,使用十六进制编辑器可以做到这一点。我认为这是我最感兴趣的方法。

如何为现有的二进制可执行文件添加功能?一件事

博客文章。

http://charlessolar.com/post/tag/disassemble

此堆栈溢出问题。
/>
https://stackoverflow.com/questions/9449845/how-to-link-object-file-to-executable-compiled-binary

评论

您是否要在单个特定的二进制文件中绕行?还是您要制作一个通用的绕行“修补程序”,该修补程序可以在任何包含上述hello()函数之类的二进制文件上使用?

我希望大致了解该过程。

#1 楼

我在Ubuntu 14.04上编译了程序,并将其放在https://mega.co.nz/#!gdRRxRzZ!dw08GEHvXeTxXqurcpMLOxpXVjZa807TJN0PH60h4Rg;
如果要回溯以下
步骤,则可能要使用该二进制文件,因为如果您没有确切的C编译器版本和
libs,则您的二进制文件可能会有所不同。已编译的程序(detour.orig)和已修补的程序(detour.patched)。

首先,让我们使用objdump拆解二进制文件: />并检查数据部分:如您所见,字符串Helloworld位于只读数据部分中,分别为400634和40063b。这些偏移量被传递给printf中的putshello。为什么puts?好吧,优化器足够聪明,可以将以'\ n'结尾的常量字符串
的printf重写为puts;您会看到.rodata节中的字符串中省略了'\ n'。

现在,我们要插入puts("detoured")。但是hello函数中没有空间,如果我们尝试在其中插入一些字节
,则程序中的所有其他内容都会被移动,我们希望避免这种情况。另外,.rodata节中没有空格用于另一个字符串,.eh_frame_hdr直接在其后面开始。主函数在4005a6返回,并且C编译器使用一些填充在16字节边界处获取下一个
函数__libc_csu_init。这意味着我们可以利用一些未使用的字节。
在反汇编的其余部分中,我们找到了更多类似的字节:

/>其中最后一个(400615)的大小适合放入“ de回”的字符串。

现在,我们要对该程序集进行的操作将其修补为:

$ objdump -d detour.orig|less
.. stuff omitted ..
000000000040057d <hello>:
  40057d:       55                      push   %rbp
  40057e:       48 89 e5                mov    %rsp,%rbp
  400581:       bf 34 06 40 00          mov    
$ objdump  -s detour.orig | less
.. stuff omitted ..
Contents of section .rodata:
 400630 01000200 48656c6c 6f200077 6f726c64  ....Hello .world
 400640 2100                                 !.
Contents of section .eh_frame_hdr:
.. more stuff omitted ..
x400634,%edi 400586: b8 00 00 00 00 mov
4004ba          66 0f 1f 44 00 00
4004e9          0f 1f 80 00 00 00 00
400529          0f 1f 80 00 00 00 00
4005a7          66 0f 1f 84 00 00 00 00 00
400615          66 66 2e 0f 1f 84 00 00 00 00 00
x0,%eax 40058b: e8 d0 fe ff ff callq 400460 <printf@plt> 400590: bf 3b 06 40 00 mov
400590          jmp 4004e9                              e9 54 ff ff ff
4004e9          mov 
$ detour.patched
Hello detoured world!
x400615, %edi; jmp 400529 bf 15 06 40 00 eb 39 400529 callq 400460; jmp 4005a7 e8 32 ff ff ff eb 77 4005a7 mov 0x40063b, %edi; jmp 400595 bf eb 06 40 00 eb e7
x40063b,%edi 400595: e8 b6 fe ff ff callq 400450 <puts@plt> 40059a: 5d pop %rbp 40059b: c3 retq 000000000040059c <main>: 40059c: 55 push %rbp 40059d: 48 89 e5 mov %rsp,%rbp 4005a0: e8 d8 ff ff ff callq 40057d <hello> 4005a5: 5d pop %rbp 4005a6: c3 retq 4005a7: 66 0f 1f 84 00 00 00 nopw 0x0(%rax,%rax,1) 4005ae: 00 00 00000000004005b0 <__libc_csu_init>: .. more stuff omitted ..


它在400590处覆盖指令,将所需的指令放在备用字节中,在各部分之间添加跳转,
并在跳转到下一条指令之前恢复覆盖的mov。使用十六进制编辑器将这些补丁应用到二进制文件(别忘了将'detoured'字符串也移至400615
)。生成的二进制文件应与从zip修补的detour.pattern相同。

最后,我们运行已修补的程序: ,诀窍是让我们在程序中使用未使用的区域,以避免四处移动,这会破坏偏移量。任何想要写访问字符串的东西。
如果我想要可写数据,我将需要使用数据节,甚至可能对其进行扩展-但这种情况要复杂得多,因为我有要弄乱ELF标头和大小,我可能需要特定的ELF工具才能正确使用。
当前示例只需要十六进制编辑器。我什至从操作码中手工编写了十六进制编码。要进一步了解
,请使用radare2工具。

评论


我只想指出,一个(可能)还可以更改代码段的段特征以使字符串可写(在main中保留大小约束)或添加新段以将代码和数据放入其中-这将删除所有大小的限制。 (至少适用于有效的PE格式)

–user45891
2014年10月16日19:50