一起谈.NET技术,C#不为人知的秘密-缓冲区溢出

简介:   开场白  各位朋友们,当你们看到网上传播关于微软windows、IE对黑客利用“缓冲区溢出”、0day漏洞攻击的新闻,是否有过自己也想试试身手,可惜无从下手的感慨?本文将完全使用C#语言,探索那些不为人知的秘密。

  开场白

  各位朋友们,当你们看到网上传播关于微软windows、IE对黑客利用“缓冲区溢出”、0day漏洞攻击的新闻,是否有过自己也想试试身手,可惜无从下手的感慨?本文将完全使用C#语言,探索那些不为人知的秘密。

  1.本文讲述在C#中利用堆栈缓冲区溢出动态修改内存,达到改变应用程序执行流程的目的。

  2.如果你是高手,请指出本文的不足。

  3.为了让本文通俗易懂,代码将极尽精简。

  现在开始

  我们知道,当数组下标越界时,.NET会自动抛出StackOverflowException,这样便让我们可以安全的读写内存,那么我们有没有逾越这个自动检测的屏障,达到我们非常操作的目的呢?答案是有的,而且我们可以修改一些关键变量如if、switch的判断值,for循环变量i值,甚至方法返回值,当然理论上还可以注入代码、转移代码执行区块,前提是必须在unsafe代码里。

  方法在被调用时,系统会进行以下几项操作:将该方法入栈、参数入栈、返回地址入栈、控制代码区入栈(EIP入栈)。我们想要访问方法的栈内地址,常规的托管代码是不行的,只能使用unsafe代码,但也并不是说你非要精通C/C++语言和指针操作,本文的例子都非常简单,完全可以将指针就认为是简版C#数组。

  改变临时变量的值

  先给出一段代码,然后再详细解释原理。

 代码

static  unsafe void Main(string[] args)
        {
            //在栈上申请一个只能保存一个int32的内存段
            int* p = stackalloc int[1];

            for (var i = 0; i < 30; i++)
            {
                System.Threading.Thread.Sleep(200);

                Console.WriteLine("{0}\n", i);
                p[i] = 0;
            }
           
            Console.ReadLine();
        }

  这是一个既简单,但是对于从没有尝试这样写过代码的开发者来说,又颇耐人寻味,C#(包括C/C++)不会去检查指针p的偏移量是否越界,那么这段代码将会顺利编译并运行,那么for循环会顺利执行30次吗?还是......

  结论是,这将是一个死循环,因为p不断的递增1偏移,并将附近的内存的值全改为0,而局部变量i是靠p最近的变量,所有当p[i]的偏移地址等于i的地址时,代码p[i]=0就等价于i=0,实际上我在测试中i=6的时候i的值就被覆盖为0了,我在代码中添加了Thread.Sleep(200)和Console.WriteLine("{0}\n", i)就是让大家能更直观的看到程序的执行过程,当然这里也可以改为p[i]=1,p[i]=2等数字

  搜索内存值并修改

  还是先给出代码

代码
static  unsafe void Main(string[] args)
        {
            Console.WriteLine(Change_Result());
            Console.ReadLine();
        }

        static unsafe int Change_Result()
        {
           
            int i = 0;
            //变量result,默认的返回值
            int result = 123;
            //申请一段栈内存,大小可随意设置
            int* p = stackalloc int[1];
            //从当前栈地址开始向下查找与函数返回值相匹配的地址,一旦匹配则修改为10000
            while (true)
            {
                if (p[++i] == 123)
                {
                    p[i] = 10000;
                    break;
                }
            };
            return result;
        }

  变量result作为方法的返回值默认为123,并且没有任何显式修改其值的代码,关键在这里

 
 
while (true)
{
if (p[++i] == 123)
{
p[i] = 10000;
break;
}
}

  这段代码找到值为123的内存地址(也就可能是变量result的地址),然后将其值修改为10000,当然,函数返回值就肯定不会再是原先的123咯

  这就是经典的StackOverFlow的两个例子,希望通俗易懂能让大家所接受,另外缓冲区溢出并不只是改变内存的值,在高手的手里,他还可以执行任意代码,因为方法执行的时候总会有一个指针指向方法即将执行的下一条指令,如果控制了这个指针,就控制了进程。

目录
相关文章
|
9天前
|
数据采集 C# 数据安全/隐私保护
掌握 C# 爬虫技术:使用 HttpClient 获取今日头条内容
本文介绍了如何使用C#的HttpClient与爬虫代理IP技术抓取今日头条内容,以实现高效的数据采集。通过结合亿牛云爬虫代理,可以绕过IP限制,增强匿名性。文中提供了一个代码示例,展示如何设置代理服务器信息、请求头,并用正则表达式提取热点新闻标题。利用多线程技术,能提升爬虫采集效率,为市场分析等应用提供支持。
掌握 C# 爬虫技术:使用 HttpClient 获取今日头条内容
|
8月前
|
C#
45【软件技术基础】C#调用NPOI插件对EXCEL进行处理
NPOI插件进行EXCEL表格处理,不依赖第三方软件,功能强大,使用简便。 C#调用NPOI插件进行EXCEL单个表和文件夹中批量表的处理。
141 1
|
8月前
|
C# 开发者
C# 开发者技术:进程间数据共享之管道(Pipes)-异步通信版
主要类 1.NamedPipeClientStream 2.NamedPipeServerStream 解释:命名管道是一种进程间通信的方式,它允许不同进程之间在同一台机器上进行通信
446 2
C# 开发者技术:进程间数据共享之管道(Pipes)-异步通信版
|
12月前
|
缓存 前端开发 JavaScript
采用.Net Core技术框架开发的医院云LIS平台源码,B/S架构
基于B/S架构的医学实验室检验系统源码,整个系统的运行基于WEB层面,只需要在对应的工作台安装一个浏览器软件有外网即可访问。全套系统采用云部署模式,部署一套可支持多家医院检验科共同使用。 采用.Net Core新的技术框架、DEV报表、前端js封装、分布式文件存储、分布式缓存等,支持LIS独立部署,Docker部署等多种方式。
C#面向对象程序设计课程实验五:实验名称:C#面向对象技术
C#面向对象程序设计课程实验五:实验名称:C#面向对象技术
C#面向对象程序设计课程实验五:实验名称:C#面向对象技术
|
设计模式 缓存 NoSQL
U3D客户端框架之类对象池技术优化C#语言GC
类对象池,类似对象池,顾名思义就是一定数量的已经创建好的类对象(Object)的集合。当需要创建对象时,先在池子中获取,如果池子中没有符合条件的对象,再进行创建新对象,同样,当对象需要销毁时,不做真正的销毁,而是将其对象SetActive(false),并存入池子中。这样就避免了大量对象的创建销毁,减少了GC,优化了性能。
C#实战:基于ItextSharp技术标签生成小工具
今天给大家分享小编基于ItextSharp制作的一款标签生成小工具,可供大家学习或者二次开发满足实际的需求使用。 使用技术:C\#+ItextSharp+Winfrom+Net4.0
C#实战:基于ItextSharp技术标签生成小工具
|
安全 NoSQL MongoDB
.Net线程同步技术解读
C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。
.Net线程同步技术解读
|
移动开发 负载均衡 前端开发
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
143 0
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
|
网络架构
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)
162 0
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)