gdb
分解了以下代码: │0x7ffff76f7e4b <_ZN16CRRegistratorImp8RegisterEbPv+587> je 0x7ffff76f7ce6 <_ZN16CRRegistratorImp8RegisterEbPv+230> │
│0x7ffff76f7e51 <_ZN16CRRegistratorImp8RegisterEbPv+593> mov rdi,QWORD PTR [rbp+0x10] │
│0x7ffff76f7e55 <_ZN16CRRegistratorImp8RegisterEbPv+597> mov rax,QWORD PTR [rdi] │
│0x7ffff76f7e58 <_ZN16CRRegistratorImp8RegisterEbPv+600> call QWORD PTR [rax+0x30] │
│0x7ffff76f7e5b <_ZN16CRRegistratorImp8RegisterEbPv+603> test al,al │
│0x7ffff76f7e5d <_ZN16CRRegistratorImp8RegisterEbPv+605> je 0x7ffff76f7ce6 <_ZN16CRRegistratorImp8RegisterEbPv+230> │
│0x7ffff76f7e63 <_ZN16CRRegistratorImp8RegisterEbPv+611> jmp 0x7ffff76f7d29 <_ZN16CRRegistratorImp8RegisterEbPv+297>
│0x7ffff76f7e68 <_ZN16CRRegistratorImp8RegisterEbPv+616> xor edx,edx │
│0x7ffff76f7e6a <_ZN16CRRegistratorImp8RegisterEbPv+618> mov rsi,r12 │
│0x7ffff76f7e6d <_ZN16CRRegistratorImp8RegisterEbPv+621> mov rdi,rbp │
│0x7ffff76f7e70 <_ZN16CRRegistratorImp8RegisterEbPv+624> call 0x7ffff7596518 <_Z18CallRegGuiCallbackP13CRRegistratorPv13ERegGUIAction@plt> │
│0x7ffff76f7e75 <_ZN16CRRegistratorImp8RegisterEbPv+629> jmp 0x7ffff76f7e41 <_ZN16CRRegistratorImp8RegisterEbPv+577> │
│0x7ffff76f7e77 <_ZN16CRRegistratorImp8RegisterEbPv+631> mov edx,0x4 │
│0x7ffff76f7e7c <_ZN16CRRegistratorImp8RegisterEbPv+636> mov rsi,r12 │
│0x7ffff76f7e7f <_ZN16CRRegistratorImp8RegisterEbPv+639> mov rdi,rbp │
│0x7ffff76f7e82 <_ZN16CRRegistratorImp8RegisterEbPv+642> call 0x7ffff7596518 <_Z18CallRegGuiCallbackP13CRRegistratorPv13ERegGUIAction@plt>
这不是整个过程,但我认为不需要。我想知道的是,如何到达地址
0x7ffff76f7e68
(+616
)。 我以为在此过程中的某处会找到类似以下说明的内容:
jmp 0x7ffff76f7e68 <_ZN16CRRegistratorImp8RegisterEbPv+616>
,但是此过程中没有此类说明,并且不是可能到达那里,因为在地址
+611
上有jmp
指令。所以我有以下问题:它是死代码吗?
是否可以从其他过程直接跳转到该特定地址(
+616
)?是还有另一种到达该地址的方法吗?
#1 楼
有几种可能性。至少看起来不像是垃圾,所以GDB内置的反汇编引擎可能是关于操作码的。当显示那些在反向工程中需要更多的细节时,GDB受到了一定的限制。目标。实际上,这可能是无效代码,因为名称表明这是C ++代码。因此,总是有机会永远不会引用某些虚函数,而是将它们保留在二进制文件中。本质上,有些极端情况会导致代码失效。但是,很难在这个小窗口中分辨出您所提供的目标,而又没有有关目标的更多知识。
首先,我将首先分解名称,因为您似乎具有用于的调试符号该应用程序:
CRRegistratorImp::Register(bool, void*)
CallRegGuiCallback(CRRegistrator*, void*, ERegGUIAction)
根据此列表,您可以看到Linux ABI(系统V AMD64 ABI)在x86- 64:RDI,RSI,RDX,RCX,R8,R9,XMM0-7。
从这些知识中,我推断出这可能是两个很小的包装函数,可以完成类似的工作:
; first function
xor edx,edx
mov rsi,r12
mov rdi,rbp
call 0x7ffff7596518 <_Z18CallRegGuiCallbackP13CRRegistratorPv13ERegGUIAction@plt>
jmp 0x7ffff76f7e41 <_ZN16CRRegistratorImp8RegisterEbPv+577>
; second function below
mov edx,0x4
mov rsi,r12
mov rdi,rbp
call 0x7ffff7596518 <_Z18CallRegGuiCallbackP13CRRegistratorPv13ERegGUIAction@plt>
大致(分别:
CallRegGuiCallback($RDI, $RSI, 0);
CallRegGuiCallback($RDI, $RSI, 0x4);
如果没有适当的反汇编程序,您将无法确定代码已死(==未引用)GDB对此工具而言太粗糙了,即使使用适当的反汇编程序,即使反汇编程序“合理”,您也不会100%确信它是无效代码。 br />
也就是说,给radare2(免费,开源),Hopper(c商用,但价格合理)或IDA Pro(商用,但价格相对昂贵,但功能非常强大)。这些应该使您对代码的其他部分所引用的代码的部分有了一个更好的了解。
回答您的问题:
是无效代码吗?
可能,但是无法确定(即排除假阴性!)。
可以直接从其他过程直接跳转到该特定地址(+616)吗?
从语义上讲,
jmp
实际上甚至可能就足够了,因为这些小的函数似乎将参数传递给了call
自己。还有另一种到达该地址的方法吗?
是的,从我的头顶上我最多可以想出六打或因此,可能还有更多偷偷摸摸的人。但是,该(子)问题有些悬而未决。无论如何,您可以使用或使用任何类型的条件跳转。您可以
jmp
,也可以将地址加载到寄存器中,然后进行间接call
,或者可以混淆地址,将其加载到寄存器中,然后进行任何类型的位处理和算术运算以及间接调用,或者可以使用最终将调用此特定代码块的vtable。在这种情况下,较大的反汇编块可能会有所帮助。