zoukankan      html  css  js  c++  java
  • windows2000 堆溢出 利用原理

    源于0day安全一书

    1.堆的分配原理

      申请堆空间   HANDLE address =  HeapCreate(0,0x1000,0x10000)         

      address就是堆的地址

      在address+0x178 偏移处,是空表(用于管理堆的申请释放,里面都是空闲的堆)

      

       空表的结构(书上的):

        解释一下:free是一个指针数组(数组里面全是指针,可以理解为 Node * 类型的指针,其实就是前后堆的地址)

        指针类型是自定义的数据结构  ,大概像这样: 

        stuct Node

        {

          Node * flink;   //指向上一个Node,这个就是堆的地址

             Node * blink; //指向下一个Node,这是另一个堆的地址

        };

        简单一点:free里面每一项都是一个地址,通过这个地址能找到一个8字节的数据(Node),在这8字节数据中,前4字节和后4字节都是地址(地址里面保存的是别的Node的地址)。然后互相保存地址,就形成了双向链表。

        free数组每一项保存的虽然都是地址,但是堆的地址是分大小的。看图可得,每一项指向多大的堆。

        如果空表里面一项是空的(没有合适大小的堆),那么它保存的两个地址都是自己。

      空闲堆的结构:

           

        在堆溢出中有用的就这几个:

        self Size :堆大小(一个单位是8字节,而且要算上block head大小)        

        Flags:状态

        Flink in freelist:前一个的地址   Blink in freelist:后一个的地址

        这就是free[0]指向的堆,就这一个堆:

                  

        因为没有别的堆了,所有两个地址均指向0x520178,就是free[0]

        

        当使用  HLOCAL   h1 = HeapAlloc(address,HEAP_ZERO_MEMORY,8);申请8字节堆空间。

        之前保存地址的位置变成0了,堆就从这里开始保存填数据。

        (这是非调试态的堆)

        

        如果再 HeapFree(address,0,h1);把这个堆释放了。它又会在块头(见图block head)后面加上空表指针,嵌入free[2]形成新的链表

    2.错误

        在空表中,因为空间申请,导致节点的卸下,引起重新赋值,而这赋值是以块的多层指针来实现的,如果该块保存的指针被改了,就出现错误的赋值

        

             注意了:上图的(node->)等都是说的中间大大的Node

            假设待分配的块的两个地址(blink,flink指向的地址)被修改为:d1,d2

            会发生  [d1+4] = d2  , [d2] = d1;  (前提是这两个地址必须可读可写,不然会报错)

             结果就是可以让两个指定地址交换数据。

    3.利用

        一切都是在windows2000才成立,其他版本我还没学!!

       原理:程序退出时会调用ExitProcess()

          ExitProcess()将调用 RtlEnterCriticalSection() ,调用该函数是通过指针,保存该函数指针的地址是固定的,就是[PEB+0x20].

             即 0x7FFDF020 ,这个地址保存的就是RtlEnterCriticalSection的函数指针(或者说地址)

          如果在0x7FFDF020中填入另外的地址,那么它就会执行指定的地址。

        过程:

        利用memcpy函数,当拷贝的大小超过了堆的大小,会淹没掉后面空闲推的空表指针(其中就包括地址)。

        

        

         shellcode的首地址就是0x520688, 在shellcode[208]处填入shellcode地址与RtlEnterCriticalSection() 地址,

    将使得  [0x7FFDF020 ] = 0x520688,ExitProcess()想调用RtlEnterCriticalSection()时就跳到了shellcode处执行我们构筑好的代码。

        构建好的shellcode(从5030h - 覆盖空表指针)

        

         EB 04 跳过四个字节(因为四个字节将被0x7FFDF020覆盖,前面说了覆盖是双向的,书上并没有这么做,因为如果仅仅运行测试这点代码,不会有影响,但实际情况是不确定的)0x7FFDF020将被翻译成如下指令:

         

        当运行到shellcode时,需要把RtlEnterCriticalSection()的地址写回去,不然要出错

       

      MOV EAX,7FFDF020     "xB8x20xF0xFDx7F"

         MOV EBX,77F89103(这个不是固定的,得看0x7FFDF020原来保存的指针 ,自己找) "xBBx03x91xF8x77"

       MOV [EAX],EBX       "x89x18"

       其他都是shellcode,实现了弹个框。

        

      

  • 相关阅读:
    vim 真是上瘾啊
    乐此不疲
    .vimrc .bashrc
    github
    隐藏c语言烦人的{ }
    linux mint console-setup
    samsung n143 brightness on linux mint
    荒漠甘泉——1月31日
    嵌入式 方向?
    python2与python3的区别
  • 原文地址:https://www.cnblogs.com/jf-blog/p/12336818.html
Copyright © 2011-2022 走看看