什么是 *(_BYTE *)、__usercall、eax 和 edi

逆向工程 艾达 部件 C 六线谱
2021-06-24 19:33:18

我正在尝试了解有关事物如何工作的一些算法。这是我用 Hey Rays 反编译我的可执行文件得到的函数。

我想运行这个函数来查看结果,然后了解它是如何工作的。

所以我首先想知道这个函数的所有签名是什么意思?

__usercall sub_401960<eax>(int a1<edi>)
__usercall
eax and diamond <>
edi and diamond <>

然后我想知道这些东西是什么意思:

*(_BYTE *)

__security_cookie

以及他们在以下代码中所做的事情:

#include <stdio.h>
#include <stdlib.h>


int __usercall sub_401960<eax>(int a1<edi>)
{
  int result; // eax@1
  signed int v2; // esi@1
  char v3; // cl@2
  char v4; // cl@3
  char v5; // cl@8
  char v6; // cl@9
  char v7; // cl@14
  char v8; // cl@15
  char v9; // cl@20
  char v10; // cl@21

  result = 0;
  v2 = 0;
  do
  {
    v3 = *(_BYTE *)(v2 + a1);
    if ( (unsigned __int8)(v3 - 48) > 9u )
    {
      if ( (unsigned __int8)(v3 - 97) > 5u )
      {
        if ( (unsigned __int8)(v3 - 65) > 5u )
          return result;
        v4 = v3 - 55;
      }
      else
      {
        v4 = v3 - 87;
      }
    }
...
  return result;
}

对不起,如果我问过这样的新手问题

我想要的是运行的东西!

2个回答

首先,OP 多次提到他想执行该功能。使用调试器应该很容易(IDA 具有不错的调试功能,或者您可以尝试ollydbg

我将按照问题出现的顺序回答问题:

什么是__usercall函数定义中的菱形包装寄存器?

__usercall是 IDA 中的“虚拟调用约定”。这不是现实世界的调用约定,而是让 IDA 用户具体描述如何将参数传递给函数。这是当参数在一些非常规的方式通过了特别有用的,你不能使用任何__stdcall__fastcall等等。

原型中菱形包装的寄存器名称用于__usercall将特定寄存器分配给函数主体中的该变量(或返回地址)。

您获得的原型 ( __usercall sub_401960<eax>(int a1<edi>)) 表示将返回值放入eaxa1传递给 中的函数edi

什么*(_BYTE *)意思?

这实际上有两个不同的部分,一个接一个地评估。

首先,(_BYTE *)将值或寄存器转换为字节指针。这类似于将值分配给定义为 的 C 变量byte *

其次,*取消引用地址并检索该地址中的值,假设 value 是指针的类型,在我们的例子中_BYTE

这是简单的 C 语法,请在线阅读更多相关信息良好的 C 理解对逆向工程师非常有益。

什么是__security_cookie

__security_cookie堆栈金丝雀用作堆栈保护时,是在 Microsoft 的 Visual Studio 编译器中定义的变量这些是在函数开始时设置为特定(非确定性)值的变量,并在函数结束时验证为相同的值。

这样做是为了确保没有人设法使函数堆栈中定义的缓冲区溢出并覆盖返回地址。因为这样的溢出还必须覆盖__security_cookie具有未知值的 。

*(BYTE *) 表示从地址中提供的指针中取出一个字节

如果地址是 12345678 并且它持有你好

然后 x = *(byte *) (12345678 + counter) 如果 counter 是 0 x 将是 'h' 等等

截断的部分检查 [0..9a..eA..E] 并返回 0(结果或 10,9,8,7,6 到 v4
在您的查询中没有看到对 __security_cookie 的任何引用

但是如果你一般地问它是什么意思,那么你应该阅读关于堆栈金丝雀、堆栈粉碎保护、gscookie 等的内容。

它是防止堆栈/缓冲区溢出漏洞利用/漏洞的实现的一部分