2011-08-02 34 views
4

由于这里太复杂无法解释的原因,我需要在一个x86子集的平台上运行x86 GCC编译的Linux程序。这个平台没有%gs寄存器, 这意味着它必须被仿真,因为GCC依赖于%gs寄存器的存在。x86的子集没有%gs寄存器:使用%gs代替陷印模拟的二进制补丁代码?

目前我有一个包装程序,当程序试图访问%gs寄存器并且模拟它时捕获异常。但这是狗慢。有没有办法让我可以提前使用等效指令对ELF中的操作码进行修补,以避免陷阱 - 仿真?

回答

3

(这是假设亚当Rosenfields的解决方案是不适用的,或类似的做法,可能是一个更好的办法。解决这个问题。)

你还没有说你如何仿效%GS寄存器,但它可能会很艰难修补一般每使用,除非你有关于程序的一些特殊的知识,否则你只有2个字节(在最糟糕的情况下,你可以用你的补丁修改)。当然,如果你使用类似%es =%gs的东西,它应该是相对简单的。

假设这可以以某种方式在您的情况下工作,策略是扫描ELF文件的可执行部分并修补任何使用或修改GS寄存器的指令。也就是说至少以下说明:

  • 与GS段重载前缀的任何指令(65期待分支指令在这种情况下,前缀表示别的东西)
  • push gs0F A8
  • pop gs0F A9
  • mov r/m16, gs8C /r
  • mov gs, r/m168E /r
  • mov gs, r/m64REX.W 8E /r)(如果支持64位模式)

而且任何人的指令,允许段寄存器(我不认为这是更多的人,但我不100%肯定)。

这是所有来自Intel® 64 and IA-32 Architectures Software Developer's Manual Combined Volumes 2A and 2B: Instruction Set Reference, A-Z。请注意,这些指令有时以其他前缀为前缀,有时不会,所以您应该使用library来执行指令解码,而不是盲目地搜索字节序列。

上面的一些说明应该是相对简单的,以便变成call my_patch或类似的内容,但是您可能很难找到适合两个字节并且一般工作的东西。如果你可以设置一个中断向量,那么int XXCD XX)可能是一个很好的候选者,但我不确定它会比你当前使用的方法更快。您当然需要记录哪个指令被修补出来,并且根据返回地址(您的处理程序接收到的内容)让中断处理程序(或其他)作出不同的反应。

您可能能够设置一个蹦床,如果你可以在-128..127字节找房并使用JMP rel8EB cb)跳到蹦床(通常是另一个JMP,但这次的目标地址更多的空间),然后处理指令仿真并跳回修补%gs使用后的指令。

最后,我建议保持陷阱和模拟代码运行,以捕捉任何你可能没想过的情况(例如自修改或注入代码)。这样您也可以记录任何未处理的案例并将其添加到您的解决方案中。

+0

现在我们正在拦截访问不存在的%gs寄存器导致的页面错误,请问双字节中断方法比拦截页面错误更快? –

+0

@Phillip:由于我不知道你的执行环境,我不知道是否可以安装一个中断处理程序,而且据我所写,它可能不会更快(你需要自己计算) 。我只提到使用中断,因为它是一个双字节指令,允许“远程跳转”。我会建议使用'int3'('CC'),这会导致一个'SIGTRAP',但这会干扰调试。 – user786653

4

您是否尝试过使用-mno-tls-direct-seg-refs选项编译代码?从我的GCC手册页(i686的 - 苹果darwin10-GCC-4.2.1):

-mtls-direct-seg-refs 
    -mno-tls-direct-seg-refs 
     Controls whether TLS variables may be accessed with offsets from 
     the TLS segment register (%gs for 32-bit, %fs for 64-bit), or 
     whether the thread base pointer must be added. Whether or not this 
     is legal depends on the operating system, and whether it maps the 
     segment to cover the entire TLS area. 

     For systems that use GNU libc, the default is on. 
+0

我认为这是FS为32位和GS为64位? – Mehrdad

+0

@Merhdad:我认为它是特定于操作系统的。在Mac OS X v10.6中,32位和64位可执行文件似乎在我刚刚进行的测试中使用GS; Linux 2.6.32也使用64位的GS。 –

+0

我实际上在谈论Windows,对不起(参见[这里](http://en.wikipedia.org/wiki/X86-64#Windows))。不知道其他人。 – Mehrdad