IDA 技巧(77) 映射变量

admin 2024年11月25日15:58:04评论30 views字数 3504阅读11分40秒阅读模式

快速重命名在处理复制数据的代码时非常有用,因为变量名保持相同或相似。

然而,有时可以完全消除重复变量。

重复变量的原因

即使在源代码中一个特定变量可能只出现一次,但在机器代码层面并不总是如此。例如,大多数算术操作使用机器寄存器,因此必须将值从内存移动到寄存器以执行它们。相反,有时必须将值从寄存器移动到内存,例如:

  • 获取变量的引用/地址需要它驻留在内存中;
  • 当可用寄存器太少时,一些变量必须被溢出到栈中;
  • 当调用约定使用栈来传递参数时;
  • 递归调用或闭包通常通过将当前变量存储在栈上来实现;
  • 其他一些情况。

所有这些意味着在函数的生命周期中,同一个变量可能出现在不同的位置。尽管反编译器尽力将这些不同位置合并为一个变量,但并不总是可能,因此在伪代码中可能会出现额外的变量。

示例

一个简单的例子,我们可以回到上一篇文章中的kprocesshacker.sys中的驱动入口。初始输出如下:

NTSTATUS __stdcall DriverEntry(_DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath)
{
  NTSTATUS result; // eax
  NTSTATUS v5; // r11d
  PDEVICE_OBJECT v6; // rax
  struct _UNICODE_STRING DestinationString; // [rsp+40h] [rbp-18h] BYREF
  PDEVICE_OBJECT DeviceObject; // [rsp+60h] [rbp+8h] BYREF

  qword_132C0 = (__int64)DriverObject;
  VersionInformation.dwOSVersionInfoSize = 284;
  result = RtlGetVersion(&VersionInformation);
  if ( result >= 0 )
  {
    result = sub_15100(RegistryPath);
    if ( result >= 0 )
    {
      RtlInitUnicodeString(&DestinationString, L"\Device\KProcessHacker3");
      result = IoCreateDevice(DriverObject, 0, &DestinationString, 0x22u, 0x100u, 0, &DeviceObject);
      v5 = result;
      if ( result >= 0 )
      {
        v6 = DeviceObject;
        DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)&sub_11008;
        qword_132D0 = (__int64)v6;
        DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_1114C;
        DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)&sub_11198;
        DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_150EC;
        v6->Flags &= ~0x80u;
        return v5;
      }
    }
  }
  return result;
}

我们可以看到有两个看起来多余的变量:v5v6v5result的副本,驻留在r11d中,而v6DeviceObject的副本,驻留在rax中。它们似乎是出于相关原因引入的:

  1. 编译器必须将DeviceObject从栈移动到寄存器以初始化全局变量qword_132D0并修改Flags成员。它选择了寄存器rax
  2. 因为rax已经包含了result变量(在它的低位部分:eax),所以必须在此期间将其保存到其他地方(并在对DeviceObject的操作结束时移回eax);
  3. 反编译器无法自动将DeviceObjectv6合并,因为它们使用不同的存储类型(栈与寄存器),并且因为理论上对DriverObject->MajorFunction的写入可能已经改变了栈变量,所以值可能不再相同。

映射变量

仔细查看代码后,似乎v5v6可以分别被resultDeviceObject替换。在所有情况下都可以使用“映射到另一个变量”操作来让反编译器执行此操作。

IDA 技巧(77) 映射变量

映射到另一个变量

当您第一次使用它时,会出现以下警告:

IDA 技巧(77) 映射变量

警告

或者,您可以使用快捷键=(等号);最好在初始赋值时使用它,例如v6 = DeviceObject,因为这样在替换候选列表中会预先选择最佳匹配(赋值的另一侧)。在我们的例子中,我们只有一个候选,但在大型函数中,您可能有多个相同类型的变量,因此在赋值上触发操作有助于确保您选择正确的一个。

IDA 技巧(77) 映射变量

映射变量

在映射了两个变量后,输出不再提及它们:

NTSTATUS __stdcall DriverEntry(_DRIVER_OBJECT *DriverObject, PUNICODE_STRING RegistryPath)
{
  NTSTATUS result; // eax MAPDST
  struct _UNICODE_STRING DestinationString; // [rsp+40h] [rbp-18h] BYREF
  PDEVICE_OBJECT DeviceObject; // [rsp+60h] [rbp+8h] MAPDST BYREF

  qword_132C0 = (__int64)DriverObject;
  VersionInformation.dwOSVersionInfoSize = 284;
  result = RtlGetVersion(&VersionInformation);
  if ( result >= 0 )
  {
    result = sub_15100(RegistryPath);
    if ( result >= 0 )
    {
      RtlInitUnicodeString(&DestinationString, L"\Device\KProcessHacker3");
      result = IoCreateDevice(DriverObject, 0, &DestinationString, 0x22u, 0x100u, 0, &DeviceObject);
      if ( result >= 0 )
      {
        DriverObject->MajorFunction[0] = (PDRIVER_DISPATCH)&sub_11008;
        qword_132D0 = (__int64)DeviceObject;
        DriverObject->MajorFunction[2] = (PDRIVER_DISPATCH)&sub_1114C;
        DriverObject->MajorFunction[14] = (PDRIVER_DISPATCH)&sub_11198;
        DriverObject->DriverUnload = (PDRIVER_UNLOAD)sub_150EC;
        DeviceObject->Flags &= ~0x80u;
      }
    }
  }
  return result;
}

您可以看到resultDeviceObject变量现在有了一个新的注释:映射目标。这意味着其他一些变量已被映射到它们。

取消映射变量

如果您改变了主意,想看看原始伪代码的样子,或者在输出中观察到涉及映射变量的可疑内容,可以通过右键单击一个映射变量(标记为映射目标)并选择“取消映射变量”来移除映射。

IDA 技巧(77) 映射变量

取消映射变量

更多文章

立即关注【二进制磨剑】公众号

👉👉👉【IDA 技巧合集】👈👈👈
👉👉👉【Github 安全项目合集】👈👈👈
学习零基础学习 IDA 逆向
【课程完结!内容揭秘!】7 天打造 IDA 9.0 大师:从零基础到逆向精英
知识星球🪐

IDA 技巧(77) 映射变量

原文始发于微信公众号(二进制磨剑):IDA 技巧(77) 映射变量

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年11月25日15:58:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   IDA 技巧(77) 映射变量https://cn-sec.com/archives/3434771.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息