危险,横跨.NET/6/7/8三个版本的栈漏洞

文摘   2024-05-19 11:46   湖北  

点击上方蓝字 江湖评谈设为关注/星标




前言

上一篇分享了.NET8安全漏洞,CVE-2024-30045是一个栈漏洞。来看下啥是栈漏洞,本篇仅学习用途。

1.例子:

#include<stdio.h>#include<Windows.h>char* test(char* Buf){  char testBuf[8] = { 0 };  memcpy(testBuf, Buf,9 );  return testBuf;}int main(int argc, char** argv){  char Buf[65] = { 0 };  memset(Buf, 0x41, 65);  char *testBuf=test(Buf);  getchar();  return 1;}

看到testBuf字符数组长度为8,memcpy了9个长度的字符,这时候VC++会通过_RTC_CheckStackVars函数检查是否数组赋值超标了,它的第一个参数是栈顶即rsp,第二个参数则是一个结构体_RTC_framedesc 

typedef struct _RTC_vardesc {      int addr;  //rsp的偏移    int size;  //testBuf的长度,为8    char *name;//testBuf的名字  } _RTC_vardesc;    typedef struct _RTC_framedesc {      int varCount;  //变量个数,此处只有一个即testBuf    _RTC_vardesc *variables;  } _RTC_framedesc

上面代码会报错,提示栈的testBuf需要纠错。

2.把它改下:

#include<stdio.h>#include<Windows.h>char* test(char* Buf){  char testBuf[8] = { 0 };  memcpy(testBuf, Buf, 8);  return testBuf;}int main(int argc, char** argv){  char Buf[65] = { 0 };  memset(Buf, 0x41, 65);  char *testBuf=test(Buf);  testBuf[9] = 0x20;  getchar();  return 1;}

同样的testBuf[9]这个地方赋值了,却没有报错。看下内存:

0x0000004B652FFA18  41 41 41 41 41 41 41 41 cc 20 cc cc cc cc cc  AAAAAAAA???????0x0000004B652FFA27  cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc  ???????????????

看到testBuf索引9处被赋值了0x20,后面还有一堆的0xCC,表示这段内存可以随心所欲的赋值操控。这就是漏洞。

3.继续改

#include<stdio.h>#include<Windows.h>char* test(char* Buf){  char testBuf[8] = { 0 };  memcpy(testBuf, Buf,9 );  return testBuf;}int main(int argc, char** argv){  char Buf[65] = { 0 };  memset(Buf, 0x41, 65);  char *testBuf=test(Buf);  getchar();  return 1;}

我们把它还原到例子1,知道它会提示:

Run-Time Check Failure #2 - Stack around the variable 'testBuf' was corrupted.

这个提示在_RTC_CheckStackVars函数里面,会获取到testBuf的长度,通过testBuf的地址+长度然后判断testBuf的结尾是否是0xCC如果不是则表示数组索引超标了,此时就可以调用_RTC_StackFailure,以打印出错误信息:

00007FF60F0E1A7A 81 3C 28 CC CC CC CC cmp         dword ptr [rax+rbp],0CCCCCCCCh  00007FF60F0E1A81 74 0F                je          _RTC_CheckStackVars+62h (07FF60F0E1A92h)  00007FF60F0E1A83 48 8B 4C 24 28       mov         rcx,qword ptr [rsp+28h]  00007FF60F0E1A88 48 8B 54 3A 08       mov         rdx,qword ptr [rdx+rdi+8]  00007FF60F0E1A8D E8 C1 F7 FF FF       call        _RTC_StackFailure (07FF60F0E1253h)

我们可以把这个je变成jne,此时即使testBuf超索引赋值,也会造成整个程序不会报错的假象。

结尾

至于漏洞的具体利用,这里不再展示。建议尽快升级您的.NET版本。

往期精彩回顾

.NET9异常(CLR)原理(顶阶技术


江湖评谈
记录,分享,自由。
 最新文章