metasploit msgrpc c++实现远程过程调用

来源:互联网 发布:软件是什么 编辑:程序博客网 时间:2024/05/21 09:47

想入手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 哪位大侠知道还请指导下 谢!

原创粉丝点击