想入手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<string>param,std::map<string,result_object> *unmsg)//cmd为方法名,param为方法参数列表
{
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<msgpack::sbuffer>pk(&buffer);
pk.pack_array(param.size()+1);//函数名和参数的长度
pk.pack(cmd);//RPC函数名
f(param.size()!=0)
for(inti=0;i<param.size();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> param;
string rpcId;
string ip = "192.168.11.4";
int port =55553;
param.push_back("msf");
param.push_back("123");
std::map<string,result_object>results;
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 哪位大侠知道还请指导下 谢!