objdump
对其进行反汇编,修改并尝试重新组装它们。基于符号表的主要功能的地址,但是,在剥离的二进制文件上,我们只是不知道主要功能的位置。当然我可以调整整个文本部分,从ELF的原始入口点开始。
但是问题是:
如果我从重新组装的ELF的入口点开始,那我将不得不拆开该部分。可能会双重初始化一些东西,因为在我重新组装的asm代码中,我的代码为
_start
; __do_global_dtors_aux
; __libc_csu_fini
,而链接器还将这些功能附加到新的ELF中。 />现在我在这个问题上还没有策略,有人可以给我一些帮助吗?#1 楼
关键在于确定所讨论的映像是否使用“标准” C运行时库类型(glibc,musl,uclibc)。如果是这样,则可以获取入口点地址,并将该地址与这些库中的启动例程集合进行匹配,并精确定位main()位置,因为您知道哪个call
是将控制权转移到main()
的那个。 然后,该映像可能不会与任何众所周知的C运行时链接,例如,如果它是直接调用内核syscall的代码段,还是设法鞭打了自己的CRT库。 >
另一个好处是,如果该程序根本不是用C编写的,并且使用了其他花哨的语言,但这似乎超出了问题的范围,因为
main()
与这些语言无关。猜猜。#2 楼
我开始在《反向ELF 64位LSB可执行文件x86-64,gdb》中回答这个问题,但这只是针对AMD64。并将其第一个参数作为指向__libc_start_main
函数条目的指针。以下是该功能的完整说明(从其手册页开始):main
名称
__libc_start_main
-初始化例程简介
int __libc_start_main(int (*main) (int, char**, char**), int argc, char** ubp_av,
void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void (* stack_end));
描述
__libc_start_main
函数应执行执行环境的任何必要的初始化,调用带有适当参数的main函数,并处理__libc_start_main()
的返回值。如果main()
函数返回,则应将返回值传递给main()
函数。注意:尽管本规范旨在独立于实现,但进程和库的初始化可能包括: />
如果有效用户ID与真实用户ID不相同,请执行任何必要的安全检查。
初始化线程子系统。
注册
exit()
以在此动态共享库释放资源退出(或已卸载)。注册
rtld_fini
处理程序以在程序出口运行。调用初始化函数
fini
。用适当的参数调用
(*init)()
。 此列表仅作为示例。
main()
不在源标准中;请参见参考。它仅在二进制标准中。另请参见
ISO / IEC 23360的每个体系结构特定部分中的过程初始化部分。 />
因此,
exit()
不仅为您提供了main()
过程的地址,还为您提供了__libc_start_main()
,__libc_start_main
和main()
的访问权限。然后,重点是从汇编代码中提取每个自变量,这些自变量可能会因所使用的ABI(应用程序二进制接口)而有所不同(功能自变量可能会推入堆栈或特定寄存器中)。#3 楼
objdump -f exe_name
exe_name: file format elf32-little
architecture: UNKNOWN!, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00306990
上面提到的起始地址是可执行文件的主要入口点。您也可以使用gdb
(gdb) break *0x00306990
进行验证。通常,起始地址已映射到符号
_start
,因此也可以执行br /> 如果我没记错的话,
_start
会调用__libc_start_main
,而__libc_csu_init
会依次调用<43 />#4 楼
因此,我认为,在从objdump
反汇编的asm代码中,我们应该始终找到以下内容:上面的代码是addr
函数的开始地址。对吗?有什么例外吗?
评论
实际上,这取决于您使用的ABI。例如,在SystemV AMD64中,您将在寄存器%rdi中找到第一个参数。
–恐怖
2014年6月26日19:54