返回介绍

侦查挑战

发布于 2025-01-03 23:32:56 字数 3340 浏览 0 评论 0 收藏 0

简单的看一下有问题的函数( here )。

NTSTATUS TriggerUninitializedStackVariable(IN PVOID UserBuffer) {
  ULONG UserValue = 0;
  ULONG MagicValue = 0xBAD0B0B0;
  NTSTATUS Status = STATUS_SUCCESS;
 
#ifdef SECURE
  // Secure Note: This is secure because the developer is properly initializing
  // UNINITIALIZED_STACK_VARIABLE to NULL and checks for NULL pointer before calling
  // the callback
  UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable = {0};
#else
  // Vulnerability Note: This is a vanilla Uninitialized Stack Variable vulnerability
  // because the developer is not initializing 'UNINITIALIZED_STACK_VARIABLE' structure
  // before calling the callback when 'MagicValue' does not match 'UserValue'
  UNINITIALIZED_STACK_VARIABLE UninitializedStackVariable;
#endif
 
  PAGED_CODE();
 
  __try {
    // Verify if the buffer resides in user mode
    ProbeForRead(UserBuffer,
           sizeof(UNINITIALIZED_STACK_VARIABLE),
           (ULONG)__alignof(UNINITIALIZED_STACK_VARIABLE));
 
    // Get the value from user mode
    UserValue = *(PULONG)UserBuffer;
 
    DbgPrint("[+] UserValue: 0x%p\n", UserValue);
    DbgPrint("[+] UninitializedStackVariable Address: 0x%p\n", &UninitializedStackVariable);
 
    // Validate the magic value
    if (UserValue == MagicValue) {
      UninitializedStackVariable.Value = UserValue;
      UninitializedStackVariable.Callback = &UninitializedStackVariableObjectCallback;
    }
 
    DbgPrint("[+] UninitializedStackVariable.Value: 0x%p\n", UninitializedStackVariable.Value);
    DbgPrint("[+] UninitializedStackVariable.Callback: 0x%p\n", UninitializedStackVariable.Callback);
 
#ifndef SECURE
    DbgPrint("[+] Triggering Uninitialized Stack Variable Vulnerability\n");
#endif
 
    // Call the callback function
    if (UninitializedStackVariable.Callback) {
      UninitializedStackVariable.Callback();
    }
  }
  __except (EXCEPTION_EXECUTE_HANDLER) {
    Status = GetExceptionCode();
    DbgPrint("[-] Exception Code: 0x%X\n", Status);
  }
 
  return Status;
}

如果我们传入一个正确的魔数,它会填充变量以及回调参数。如果传递的值不正确那么就不会填充。这里的问题在于变量定义时并没有设置一个特定的初始值。由于该变量布局在栈上,它会拥有一个前调用函数遗留的随机垃圾值。注意到这样的一个检查(if UninitializedStackVariable.Callback…)毫无卵用并不能阻止其崩溃。

该函数的 IOCTL 码是 0x22202F。可以查看本系列教程的第十部分和第十一部分来了解 IOCTL 是如何被识别的。转入 IDA 来看看这个函数。

思考一下上图的 4 个函数块。如果比较成功我们就会命中绿色块,在这里我们的变量被填充了适当的值,此后在红色块中当回调函数被调用时也不会出什么意外。

不错,然而如果我们比较失败了,跳过了绿色快,继续下行调用函数的时候,我们调用的将是一个内核栈上的垃圾值!

这个值是不固定的,如果你尝试重现,很可能会在 Windbg 中看到不同的值。在虚拟机 BSOD 之前,让我们快速的看一下该变量距离当前栈起始位置有多远。

计算方式: 0x8a15ced0 - 0x8a15c9cc = 0x504 (1284 bytes)

让我们重新执行并对 BSOD 进行心智健全检查。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文