1. 程式人生 > >gh0st原始碼分析與遠控的編寫(二)

gh0st原始碼分析與遠控的編寫(二)



上次說了那麼多,基本上就是一個叫“大局觀”的東西,只有腦子裡有了一個軟體的設計、執行思路,才能把一個一個類寫出來,組合在一起。

Gh0st的作者是一個對程式碼有很好掌控的人,他對程式碼的組合,類之間的關係,面向物件的思想有很深入的理解。而對我們看原始碼的人來說,這種結構化、條理化的程式,閱讀起來十分輕鬆,思路也十分清晰。

廢話不多說,我們今天來看一下gh0st的上線。所謂上線,就是我們被控端啟動起來,並主動連線我們主控端,建立起TCP連線以後,主控端就可以通過相關命令來操作被控端了,這就是一臺“肉雞”的上線。

上線以後,主控端就獲取到被控端計算機的相關資訊,如下圖:

20130510_173119.jpg


介面就是完全按照老狼的gh0st教程中的介面設計的。我們開啟原始碼,看看上線,gh0st是怎麼處理的。

以後每次文章,我會把我的原始碼發上來,大家看我的原始碼就可以了。這裡先簡潔地介紹一下我的原始碼。有如下一些檔案。

20130510_173300.jpg


這是一個解決方案,其中:MainDll是被控端,一個動態連結庫的工程;DLLTest是載入dll的普通控制檯工程;PhRemote是主控端工程,MFC的介面。Bin是我們輸出資料夾,編譯好的檔案會在其中,其中又有兩個資料夾,PhRemote是主控端,server是被控端,server中放著exe和dll,點選exe就算啟動了被控端。Common中放著三個工程都可能用到的檔案。


回到程式碼上。在主控端方面,首先我們開啟了一個埠(80),來等待被控端的連線。這些工作由Activate函式完成(在PhRemote中搜索該函式找到它):


void CPhRemoteDlg::Activate(UINT uPort, UINT nMaxConnect)
{
    CString str;
    if (m_iocpServer != NULL)
    {
        m_iocpServer->Shutdown();
        delete m_iocpServer;
    }

    m_iocpServer = new CIOCPServer();
    if (m_iocpServer->Initialize(NotifyProc, this, nMaxConnect, uPort))
    {
        char hostname[256];
        gethostname(hostname, sizeof(hostname));
        HOSTENT *host = gethostbyname(hostname);
        if (host != NULL)
        {
            for ( int i=0; ; i++ )
            {
                str += inet_ntoa(*(IN_ADDR*)host->h_addr_list[i]);
                if ( host->h_addr_list[i] + host->h_length >= host->h_name )
                    break;
                str += "/";
            }
       }
        str.Format("監聽埠: %d成功", uPort);
        AddInfoList(TRUE, str);
    }
    else
    {
        str.Format("監聽埠: %d失敗”, uPort);
        AddInfoList(FALSE, str);
    }
}

首先,變數m_iocpServer,這是我們上次說到的gh0st資料傳輸使用的CIOCPServer類物件,m_iocpServer = new CIOCPServer(),為它在堆上分配記憶體。以後我們的資料傳輸,都使用該物件來完成。

之後我們呼叫了該物件一個成員函式:m_iocpServer->Initialize(NotifyProc, this, nMaxConnect, uPort),我們右鍵 - 轉到定義,可以檢視到在CIOCPServer函式的定義。

大概就是初始化socket套接字的一個過程:WSASocket > WSACreateEvent > WSAEventSelect > bind > listen > 進入監聽執行緒。這已經是socket程式設計的一個基礎了,我就不多講。不過,其中用到了Event這個概念,這是完成埠模型中用到的概念。大家可以自己網上搜索一些非同步IO模型的相關資料學習。

在m_iocpServer->Initialize函式執行完成後,等於說已經開始監聽80埠了。這個if語句中有一個for迴圈,該迴圈並沒有用上,到此為止我也不知道老狼的原始碼中為什麼會有這樣一段。它的作用是獲取本機在所有網段下的ip地址,以/分隔。

最後,監聽成功或失敗則向下面一個ListCtrl中增加一條資訊。


好,我們在轉向被控端,就是那個dll工程。我們這個DLL只有一個匯出函式,就是TestRun,執行了這個函式,等於開啟了被控端。找到該函式:

1 extern "C" __declspec(dllexportvoid TestRun(char* strHost,int nPort )
2 {
3     strcpy_s(g_strHost, _countof(g_strHost),strHost);   //儲存上線地址
4     g_dwPort = nPort;                                       //儲存上線埠
5     HANDLE hThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)main, (LPVOID)g_strHost, 0, NULL);
6   //這裡等待執行緒結束
7     WaitForSingleObject(hThread, INFINITE);
8     CloseHandle(hThread);
9 }

該函式有兩個引數,分別是主控端的IP和埠。如果不知道IP和埠,我們也不能向主控端發起連線,不是嗎?

本函式實際上是開啟了一個執行緒,執行main函式。開啟main函式,我只找關於上線的相關程式碼:

首先聲明瞭一個CClientSocket socketClient;物件,我之前說了,被控端的資料傳輸,由CClientSocket類完成。

之後:

相關推薦

gh0st原始碼分析編寫()

上次說了那麼多,基本上就是一個叫“大局觀”的東西,只有腦子裡有了一個軟體的設計、執行思路,才能把一個一個類寫出來,組合在一起。 Gh0st的作者是一個對程式碼有很好掌控的人,他對程式碼的組合,類之間的關係,面向物件的思想有很深入的理解。而對我們看原始碼的人

gh0st原始碼分析編寫(一)

    再過幾天期末考試了,還有好多要複習。。蛋都快碎了。最近在看老狼的gh0st核心程式設計,想了很久要不要寫文章,最後還是覺得很有必要,原因過一會講。     先送上老狼的gh0st無加密(lxe格式)視訊下載地址:

gh0st原始碼分析編寫(四)

  真的很久很久了,距離上一次寫gh0st的文章(http://www.mmcyy.com),過去有大半年了。總算有一個時間,我放下手裡所有的活,能夠繼續把這份努力延續下去。     以後對於gh0st的文章,就是一個一個模組的分析。原本gh

gh0st原始碼分析編寫(三)

好久不見。距離上次寫gh0st來有好久了,一是期末考試,忙不開,二是後來電腦壞了,幾天沒能上網。     昨天總算是把電腦修好了,雖說沒到一切重頭開始的地步,但是也重灌各種東西花了很久。閒下來的時間,我就來繼續分析gh0st的原始碼吧。    

看透SpringMVC原始碼分析實踐(

一、Tomcat的頂層結構及啟動過程 1.Tomcat的頂層結構        Tomcat中最頂層的容器叫Server,代表整個伺服器,Server至少包含一個Service用於具體的服務。Service主要包含兩部分,Connector和Conta

Nginx原始碼分析實踐---(一)編寫一個簡單的Http模組

在上一節中,我們通過修改配置檔案,便能讓nginx去訪問我們寫的html檔案,並返回給瀏覽器。問題是:nginx是如何檢測到我們寫的配置項的?檢測到後,nginx又是如何知道該進行什麼操作的? 本節通過親自實踐,寫一個經典的Hello World模組來了解相應的流程是如何進行的。我們採用自上

精盡MyBatis原始碼分析 - MyBatis初始化()之載入 Mapper 介面 XML 對映檔案

> 該系列文件是本人在學習 Mybatis 的原始碼過程中總結下來的,可能對讀者不太友好,請結合我的原始碼註釋([Mybatis原始碼分析 GitHub 地址](https://github.com/liu844869663/mybatis-3)、[Mybatis-Spring 原始碼分析 GitHub 地址

redis原始碼分析思考(十九)——AOF持久化

    為了解決持久化檔案很龐大以及會阻塞伺服器的 情況,redis提出一種新的持久化方案:AOF持久化。AOF持久化是redis儲存資料的另外一種方式,全稱Append Only File,與RDB持久化不同的是,AOF持久化是隻儲存從客戶端鍵入

redis原始碼分析思考(十八)——RDB持久化

    redis是一個鍵值對的資料庫伺服器,伺服器中包含著若干個非空的資料庫,每個非空資料庫裡又包含著若干個鍵值對。因為redis是一個基於記憶體存貯的資料庫,他將自己所存的資料存於記憶體中,如果不將這些資料及時的儲存在硬碟中,當電腦關機或者進行

redis原始碼分析思考(十七)——有序集合型別的命令實現(t_zset.c)

    有序集合是集合的延伸,它儲存著集合元素的不可重複性,但不同的是,它是有序的,它利用每一個元素的分數來作為有序集合的排序依據,現在列出有序集合的命令: 有序集合命令 命令 對應操作 時

redis原始碼分析思考(十六)——集合型別的命令實現(t_set.c)

    集合型別是用來儲存多個字串的,與列表型別不一樣,集合中不允許有重複的元素,也不能以索引的方式來通過下標獲取值,集合中的元素還是無序的。在普通的集合上增刪查改外,集合型別還實現了多個集合的取交集、並集、差集,集合的命令如下表所示: 集合命

redis原始碼分析思考(十五)——雜湊型別的命令實現(t_hash.c)

    雜湊型別又叫做字典,在redis中,雜湊型別本身是一個鍵值對,而雜湊型別裡面也存貯著鍵值對,其對應關係是,每個雜湊型別的值對應著一個鍵值對或多對鍵值對,如圖所示: 雜湊型別命令 命令 對應操

redis原始碼分析思考(十四)——列表型別的命令實現(t_list.c)

    列表型別是用來存貯多個字串物件的結構。一個列表可以存貯232-1個元素,可以對列表兩端進行插入(push)、彈出(pop),還可以獲取指定範圍內的元素列表、獲取指定索引的元素等等,它可以靈活的充當棧和佇列的角色。下面列出列表的命令: 列

redis原始碼分析思考(十三)——字串型別的命令實現(t_string.c)

    在對字串操作的命令中,主要有增加刪查該、批處理操作以及編碼的轉換命令,現在列出對字串物件操作的主要常用命令: 常用命令表 命令 對應操作 時間複雜度

SpringBoot SpringApplication底層原始碼分析自動裝配

目錄 丟擲問題 @SpringBootApplication註解剖析 SpringApplication類剖析 第一步:配置SpringBoot Bean來源 第二步 :自動推斷SpringBoot的應用型別 第三步:推斷SpringBoot的引導類 第四

第07章 常用類庫API_03_StringBuffer原始碼分析常用方法

在實際開發當中,我們經常會使用到字串連線的操作,如果用String來操作,則使用“+”號完成字串的連線操作。 使用String連線字串,程式碼效能會非常低,應為String的內容不可改變,解決這個問題的方法是使用StringBuffer。     St

String.split(),StringTokenizer,StringUtils.split()的原始碼分析效能比較

他們都是用來對字串進行切割 String.split(): 從jdk1.4開始,通過正則表示式進行字串的匹配切割,有可能會丟擲 PatternSyntaxException異常,返回的是切割之後的字串陣列。 String 的split 有兩個過載的方法分別是

redis原始碼分析思考(三)——字典中鍵的兩種hash演算法

      在Redis字典中,得到鍵的hash值顯得尤為重要,因為這個不僅關乎到是否字典能做到負載均衡,以及在效能上優勢是否突出,一個良好的hash演算法在此時就能發揮出巨大的作用。而一個良好的has

《Spark核心原始碼分析開發實戰》讀書筆記之一

第1章 Spark系統概述 1.1 Spark是什麼 1. Spark比Hadoop快在哪裡 (1)Spark使用記憶體計算,而Hadoop使用IO (2)Hadoop的計算是按部就班一步一步進行的,而Spark則是提前生成了DAG,優化了運算路徑   1.2 Sp

Libevent原始碼分析-----event相關的一些函式和操作

        Libevent提供了一些與event相關的操作函式和操作。本文就重點講一下這方面的原始碼。         在Libevent中,無論是event還是event_base,都是使用指標而不會使用變數。實際上,如果檢視Libevent不同的版本,就可