想入手metasploit源代码,又不知道从何而入,看了下UI部分,发现已经存在了armitage、msfgui、以及现在的收费web。浏览了下《Metasploit Remote API4.1 Guide》
运用msgrpc时需要填写正确的post类型:
POST /api/1.0HTTP/1.1
Host: RPC Server
Content-Length:128
Content-Type:binary/message
<128 bytes ofencoded data>
rpc采用msgpack,貌似是最快的吧,支持c++的说,翻看msgpack官网的文档觉得太屎了。总的还是自己参考了msfguijava程序写的。
之前没用过WinHttp,看了msdn结合wireshark捕获自己的报文,形成了如下的实例,有啥不对的还请提醒。
//1, 首先我们打开一个Session获得一个HINTERNET session句柄;
//2, 然后我们使用这个session句柄与服务器连接得到一个HINTERNET connect句柄;
//3, 然后我们使用这个connect句柄来打开Http 请求得到一个HINTERNET request句柄;
//4, 这时我们就可以使用这个request句柄来发送数据与读取从服务器返回的数据;
//5, 最后依次关闭request,connect,session句柄。
voidRPCconnetion::begin(string ip,int port,string cmd,std::vector
{
DWORD dwSize =0;
DWORD dwDownloaded =0;
LPSTR pszOutBuffer;
BOOL bResults = FALSE;
hSession =NULL,hConnect =NULL,hRequest = NULL;//全局变量,初始化
hSession =WinHttpOpen(NULL,//useragent
WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS,
0);
if(hSession)
hConnect =WinHttpConnect(hSession,
MutiiByteToWide(ip).data(),//转化为宽字符型,自己实现
port,0);//port 55553
if(hConnect)
hRequest =WinHttpOpenRequest(hConnect,
L"POST",
L"/api/1.0",
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
0);
msgpack::sbuffer buffer;
msgpack::packer
pk.pack_array(param.size()+1);//函数名和参数的长度
pk.pack(cmd);//RPC函数名
f(param.size()!=0)
for(inti=0;i pk.pack(param.at(i));//RPC参数 if(hRequest)//发送请求 bResults =WinHttpSendRequest(hRequest, L"Content-Type:binary/message-pack",//Content-Type 0, (LPVOID)(buffer.data()), buffer.size(),//strlen(strPostData), buffer.size(),//strlen(strPostData), 0);//将数据放在PostData中发送 // End the request. if (bResults) bResults = WinHttpReceiveResponse(hRequest, NULL); // Keep checking for data until there isnothing left. if (bResults) do { // Check for available data. dwSize = 0; if (!WinHttpQueryDataAvailable(hRequest, &dwSize)) { char * error; sprintf(error,"Error%u in WinHttpQueryDataAvailable.\n",GetLastError()); MessageBoxA(NULL,error,NULL,MB_OK); } // Allocate space for the buffer. pszOutBuffer = new char[dwSize+1]; if (!pszOutBuffer) { char* error; sprintf(error,"Out ofmemory\n"); MessageBoxA(NULL,error,NULL,MB_OK); dwSize=0; } else { // Read the Data. ZeroMemory(pszOutBuffer,dwSize+1); if (!WinHttpReadData( hRequest,(LPVOID)pszOutBuffer, dwSize, &dwDownloaded)) { char * error; sprintf(error,"Error%u in WinHttpReadData.\n",GetLastError()); MessageBoxA(NULL,error,NULL,MB_OK); } elseif(dwSize>0)//&&!strcmp(cmd.data(),"console.read") { msgpack::unpackedmsg; msgpack::unpack(&msg,pszOutBuffer,dwSize); msgpack::objectobj = msg.get();// unMsg(obj,unmsg);//结构体进行接受转换的类型,可参考msfgui java msgrpc.java代码 // Free the memoryallocated to the buffer. delete [] pszOutBuffer; } } } while (dwSize>0); // Report any errors. if (!bResults) { char *error; sprintf(error,"Error%d has occurred.\n",GetLastError()); MessageBoxA(NULL,error,NULL,MB_OK); } } 调用rpc的简单程序界面如下: 完成后进行简单的调用: 1、 开启服务端 Msfrpcd –S –P 123 (注意此时必须将设置为-S不使用ssl)。其中linux环境下实施简单 Winsdows msf4.4版本环境下在metasploit主目录下新建如下bat文件即可,设置rpc服务端 @echo off set BASE=%~dp0 cd "%BASE%" setPATH=%BASE%ruby\bin;%BASE%java\bin;%BASE%tools;%BASE%svn\bin;%BASE%nmap;%BASE%postgresql\bin;%PATH% IF NOT EXIST "%BASE%java" GOTONO_JAVA set JAVA_HOME="%BASE%java" cd "%BASE%msf3" start ruby msfrpcd -S -P 123//设置自己的参数即可 2、 运用上面Cpp 的代码,注意配置好msgpack的环境变量(可baidu得到) 代码实例如下: RPCconnetion rpc ; //前面代码封装到此类 string str; string rpcToken; std::vector string rpcId; string ip = "192.168.11.4"; int port =55553; param.push_back("msf"); param.push_back("123"); std::map rpc.begin(ip,port,"auth.login",param,&results); if((results.find("result")->second).type==STRING_OBJECT) if(!(results.find("result")->second).str.compare("success")) rpcToken=results.find("token")->second.str;//获取临时型的token // rpcToken = "perxx";//永久的token param.clear(); param.push_back(rpcToken); results.clear(); rpc.begin(ip,port,"console.create",param,&results); if((results.find("id")->second).type==STRING_OBJECT) rpcId = results.find("id")->second.str;//少判断 param.clear(); param.push_back(rpcToken); param.push_back(rpcId); results.clear(); rpc.begin(ip,port,"console.read",param,&results);//每次新建的console会产生新的banner str.append(results.find("data")->second.str); param.clear(); param.push_back(rpcToken); param.push_back(rpcId); param.push_back("nmap -O192.168.11.19 -oX www\n"); results.clear(); rpc.begin(ip,port,"console.write",param,&results); param.clear(); param.push_back(rpcToken); param.push_back(rpcId); results.clear(); rpc.begin(ip,port,"console.read",param,&results); bool busy =results.find("busy")->second.b; while(busy) { Sleep(5000); results.clear(); rpc.begin(ip,port,"console.read",param,&results); str.append(results.find("data")->second.str); busy = results.find("busy")->second.b; } rpc.disconnect(); //string str ="xiaohu\nweiwu\n"; //linuxstr2str(&str); result_view.SetWindowText((LPCTSTR)str.c_str()); 3、 Ruby msgpack rpc辅助调试 Linux环境下直接msfrpc –a server_ip –S –P 123 Windows下与上面类似在最后一行换成start ruby msfrpc –a server_ip –S –P 123 //startruby msfrpcd -S -P 123 相关命令行有:rpc.call(“auth.login”,”msf”,”123”)等,可参考metasploit remote api 不过最近的简版程序中,一直报unpack_error异常insufficient bytes 哪位大侠知道还请指导下 谢!