【问题标题】:Help deciphering a few lines of assembly帮助破译几行汇编
【发布时间】:2011-03-28 01:19:32
【问题描述】:

我在ollydbg中找到了这几行汇编:

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address
MOV EDX,DWORD PTR DS:[ECX]
MOV EAX,DWORD PTR DS:[EDX+116]
CALL EAX

谁能告诉我这里发生了什么?

【问题讨论】:

  • @x0n - 作业标签从何而来?
  • 这不是作业,我只是不擅长组装。
  • 你反汇编的这个程序......它与现实世界中我们可能想象的“非常非常相似”有什么相似之处?

标签: pointers assembly x86 dword ollydbg


【解决方案1】:

这是对存储在结构中的函数指针的调用。

第一行获取存储在地址DS:xxxxxxxx 的指针。方括号表示地址的解引用,很像C中的*。来自内存的值即将用作指针;它被放入ecx 寄存器中。

MOV ECX,DWORD PTR DS:[xxxxxxxx] ; xxxxxxxx is an address

第二行取消引用上面获得的指针。来自ecx 的值现在用作地址,该地址被取消引用。在内存中找到的值是另一个指针。第二个指针被放入edx 寄存器中。

MOV EDX,DWORD PTR DS:[ECX]

第三行再次取消引用内存;这一次,从上面获得的指针0x116字节开始访问地址offset。这不能被 4 整除,所以这个函数指针似乎不是来自 C++ vtable。从内存中获取的值这次存储在寄存器eax中。

MOV EAX,DWORD PTR DS:[EDX+116]

最后,eax指向的函数被执行。这只是通过函数指针调用函数。该函数似乎接受零参数,但我有一个关于修改我的答案的问题:在这个 sn-p 之前是否有 PUSH 指令?这些将是函数参数。问号表示这个函数可能会返回一个值,我们无法从有利位置判断。

CALL EAX

总的来说,sn-p 代码看起来像是从插件库调用到 OllyDbg 的扩展函数。 OllyDbg ABI 指定了各种structs,其中包含一些函数指针。还有函数指针数组,但双间接到达edx-held 指针(也是未对齐的偶数偏移量)让我认为这是struct 而不是数组函数指针或 C++ 类的 vtable。

换句话说,xxxxxxxx 是一个指向包含函数指针的struct 的指针。

在 OllyDbg 源文件 PlugIn.h 中有一些候选的struct 定义。这是一个例子:

typedef struct t_sorted {              // Descriptor of sorted table
  char           name[MAX_PATH];       // Name of table, as appears in error
  int            n;                    // Actual number of entries
  int            nmax;                 // Maximal number of entries
  int            selected;             // Index of selected entry or -1
  ulong          seladdr;              // Base address of selected entry
  int            itemsize;             // Size of single entry
  ulong          version;              // Unique version of table
  void           *data;                // Entries, sorted by address
  SORTFUNC       *sortfunc;            // Function which sorts data or NULL
  DESTFUNC       *destfunc;            // Destructor function or NULL
  int            sort;                 // Sorting criterium (column)
  int            sorted;               // Whether indexes are sorted
  int            *index;               // Indexes, sorted by criterium
  int            suppresserr;          // Suppress multiple overflow errors
} t_sorted;

那些例子可以是NULL,并且你的asm sn -p 不会检查函数指针中的NULL 指针。因此,它必须是来自t_tableDRAWFUNCSPECFUNCt_dump

您可以创建一个包含头文件的小项目,并使用printf()offsetof() 来确定其中任何一个是否位于0x116 的偏移量。

否则,我想 OllyDbg 的内部是用同样的风格编写的。因此,在 OllyDbg 中可能有用于各种目的的私有 struct 定义(未在 Plugin.h 文件中发布)。


我想补充一点,我认为 OllyDbg 资源不可用很遗憾。我的印象是它包含的静态链接反汇编程序是在某种 ?GPL 许可下,但我没有任何运气将源代码提供给 OllyDbg。

【讨论】:

  • “这可能是一个调用...”会更准确,不是吗?你不知道它到底是什么。
  • @x0n。不,我想我很清楚它是什么。我对 OllyDbg 有一些经验。例如,我永远不会写任何类似“OllyDbg 可能是用一种不确定的高级语言编写的”的东西。它是用 MSVC 2005 编译的,我拥有特定领域的知识。当然,sn-p 可能是内联汇编,但是编写了一个或三个 OllyDbg 插件和一个人造 OllyDbg 插件主机测试工具......我想我知道它是什么。 xoff。
  • @heath:我没有把他的问题读成“这个程序集是 ollydbg 程序的一部分”。我把它读作“我用 ollydbg 反汇编了一些东西,并在被调试者中找到了这些指令。”
  • @x0n。那么我知道你从哪里来。是的,我最初猜测是“C++ vtable”,所以我希望我在初稿中写了“可能”。后来我 92% 确定它是插件或内部 ABI 的一部分。
  • @heath - @iron 刚刚在我的另一篇文章中通过评论确认 ollydbg 确实不是目标,因此可能更有可能使用 vtable。
【解决方案2】:

从地址 xxxxxxx 中取出 32 位数字,放入 ECX 寄存器,然后将此值作为地址,读取该值放入 EDX 寄存器,最后将该数字加 116 并读取该地址的值进入 EAX。然后它开始在现在保存在 EAX 中的地址处执行代码。当该代码遇到返回操作码时,将在调用指令之后继续执行。

这是非常基本的组装。这让我想知道你正在使用调试器做什么以及你的任务何时到期;-)

【讨论】:

  • 我正在通过调试东西学习汇编,所以它是基本的也就不足为奇了。我知道它做了什么,但我没有在“MOV ECX,DWORD PTR [地址]”和“MOV EDX,DWORD PTR [ECX]”中看到一点,所以我认为它可能在做一些不明显的事情.那么无论如何,这是否意味着 xxxxxxxx 是指向函数的指针,还是指向函数的指针?
  • 除了它的意思之外,没有别的意思。你不能推断那里有一个“函数”,或者即使函数作为一个概念存在于编译的任何高级语言中(或者即使涉及更高级别的语言,tbh)为了对这段代码进行逆向工程,你需要对生成它的编译器有深入的了解。
  • 我知道是 MSVC++,可能是 2005 年。
  • @iron: 好的,现在去反汇编 MSVC 来弄清楚它的编译策略。糟糕!
  • 更严重的是,你应该试试 IDA Pro 反汇编器——它比大多数都提供更多信息,而且 4.9 版本是免费的[非商业用途] - hex-rays.com/idapro
【解决方案3】:

自从我做 ASM (1997) 以来已经有一段时间了,即使那时我也只做 i386 ASM,所以如果我的回答不是很有帮助,请原谅我......

不幸的是,这 4 行代码并没有告诉我太多信息。它主要只是将东西加载到 CPU 寄存器中并调用一个函数。

具体来说,看起来像是数据或指针正在从该地址加载到您的 CX 寄存器中。然后将该值从 CX 复制到 DX。所以你有位于 DX 中的 CX 指针的值。然后 DX 中的值加上 116 的偏移量被复制到 AX 寄存器(你的累加器?)

然后执行复制到 AX 中的位于该地址的任何函数。

【讨论】:

  • 它是否将其修改为 DWORD PTR 已经是 DWORD PTR 的东西?
  • 我没有看到任何修改正在进行,但是调用 EAX 可能会调用一些确实做一些修改的东西。我不能说不知道那里有什么......
  • 我很确定它会将 DS:[ECX] 指向的值加载到 EDX 中,而不是像 x0n 所说的那样简单地将 ECX 复制到 EDX。
  • 好点。就像我说的那样,已经有一段时间了……相应地进行了调整。
【解决方案4】:

考虑到关于编译器是 MSVC 的 cmets,我 99% 确定这是一个虚拟方法调用。

MOV ECX,DWORD PTR DS:[xxxxxxxx]

指向类实例的指针从全局变量加载到 ECX 中。 (注意:默认的 __thiscall 调用约定使用 ECX 传递实例指针,也就是 this 指针)。

MOV EDX,DWORD PTR DS:[ECX]

vftable(虚函数表)指针通常是类布局中的第一项。这里指针被加载到 EDX 中。

MOV EAX,DWORD PTR DS:[EDX+116]

将表中偏移量 116 (0x74) 处的方法指针加载到 EAX 中。由于每个指针是 4 个字节,这是类的第 30 个虚方法 (116/4 + 1)。

CALL EAX

方法被调用。

在原始 C++ 中,它看起来像这样:

g_pObject1->method30();

想了解更多关于MSVC对C++类的实现,包括虚方法,请看我的文章here

【讨论】:

    猜你喜欢
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 1970-01-01
    • 2011-09-26
    • 1970-01-01
    相关资源
    最近更新 更多