NameLess后門技術(shù)分析全接觸(1) |
發(fā)布時(shí)間: 2012/9/15 20:10:08 |
NameLess的大名都應(yīng)該聽(tīng)說(shuō)過(guò)吧,估計(jì)還有相當(dāng)多的人用過(guò)呢,個(gè)人認(rèn)為這個(gè)后門非常經(jīng)典,我們?cè)賮?lái)簡(jiǎn)單看一下有關(guān)它的介紹:僅有一個(gè)DLL文件,平時(shí)不開(kāi)端口,可以進(jìn)行反向連接的后門程序。 這個(gè)后門早已經(jīng)開(kāi)源了,網(wǎng)上流傳最廣的是V1.14(穩(wěn)定版),(我已經(jīng)把這個(gè)版本的完整源代碼打包了)哈哈,這樣的好事可千萬(wàn)不能錯(cuò)過(guò)哦,立馬從網(wǎng)上Down回來(lái)研究了下,越讀越覺(jué)得越有味道,就把一些東西分享出來(lái)吧,希望對(duì)各位能有所幫助。 對(duì)于一個(gè)較完整的后門來(lái)說(shuō),最需要關(guān)心的地方莫過(guò)于幾點(diǎn):?jiǎn)?dòng)方式、連接方式、控制功能、自身保護(hù)。而NameLess就具備了一個(gè)完整后門的所有功能,我們就通過(guò)品讀它的代碼來(lái)啟發(fā)自己能做出一個(gè)屬于自己的后門吧。 首先將源代碼文件解壓,鼠標(biāo)雙擊NameLess.dsw文件打開(kāi),我的測(cè)試環(huán)境是VC6.0,更高的版本我沒(méi)測(cè)試過(guò)(沒(méi)安裝),為了方便分析,我同時(shí)使用EditPlus將其打開(kāi)了,便于快速查找各函數(shù)的定義跟蹤流程。 一、啟動(dòng)方式 NameLess后門的安裝方法:打開(kāi)CMD窗口,轉(zhuǎn)到后門放置的目錄,輸入Rundll32 NameLess.dll,Install ServiceName ActiveString Password。 可見(jiàn)它是通過(guò)系統(tǒng)提供的Rundll32程序來(lái)進(jìn)行安裝的(畢竟它只有一個(gè)DLL文件),安裝函數(shù)代碼在輸出的Install函數(shù)中,我們?cè)谠垂こ讨姓业竭@個(gè)函數(shù)并跟蹤到InstallService(param)中,一目了然。 作者首先用自寫的DesStringArgument函數(shù)把命令行參數(shù)給分解出來(lái),再用自寫的ReadRegEx函數(shù)檢查注冊(cè)表鍵HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\NameLess(我們下面用“注冊(cè)表路徑1來(lái)代替這個(gè)路徑”)是否存在,然后進(jìn)入HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\"ServiceName"(注冊(cè)表路徑2)把start的值改為2,接著進(jìn)入子項(xiàng)“Parameters”中把原服務(wù)的ServiceName讀取出來(lái)后保存到注冊(cè)表路徑1中,隨后把自身的一些信息比如密碼、替換的服務(wù)名也保存在這里以備卸載的時(shí)候恢復(fù)。后面緊接著就是卸載函數(shù)RemoveService,大概流程就是先判斷密碼是否正確,然后到“注冊(cè)表路徑1”中找到原服務(wù)的文件路徑進(jìn)行恢復(fù),然后刪除掉“注冊(cè)表路徑1”。(代碼我就不貼了,見(jiàn)附件源工程中的NameLess.cpp文件) 這種啟動(dòng)方法只需替換掉系統(tǒng)中原有不太重要的服務(wù),在當(dāng)時(shí)來(lái)說(shuō)效果應(yīng)該是比較好的,不過(guò)隨著現(xiàn)在主動(dòng)防御的大行其道,這種直接修改注冊(cè)表的方法已失去了效果,畢竟是兩年前的作品了。但主動(dòng)防御也不是無(wú)懈可擊,它畢竟還是要被用戶控制的(技術(shù)是要為用戶服務(wù)的),所以我們可以綜合利用各種方法將自己完美地偽裝好后欺騙用戶的允許,順利地Pass,所以說(shuō)“人”才是網(wǎng)絡(luò)安全中最薄弱的一環(huán)。 二、連接方式 現(xiàn)在我們的后門可以啟動(dòng)了,但它是如何工作的呢?我們知道如果程序以服務(wù)方式啟動(dòng)的話,在DLL中必須導(dǎo)出一個(gè)ServiceMain函數(shù),所以我們就在NameLess.cpp文件中找到該函數(shù)開(kāi)始我們的分析過(guò)程。 這里先注冊(cè)了一個(gè)服務(wù)控制函數(shù)ServiceHandler以便控制服務(wù)的啟動(dòng)、暫停等行為,具體的實(shí)現(xiàn)在TellSCM函數(shù)中,這個(gè)函數(shù)是通過(guò)調(diào)用API函數(shù)SetServiceStatus實(shí)現(xiàn)的,沒(méi)什么新意。我們回到ServiceMain函數(shù)中繼續(xù)看,就剩下一個(gè)調(diào)用了:RealService,看樣子是從這里開(kāi)始了真正的工作。 在RealService函數(shù)中經(jīng)過(guò)一系列的讀取注冊(cè)表初始化后程序創(chuàng)建了一個(gè)保護(hù)線程,(該線程函數(shù)ShieldThread的實(shí)現(xiàn)代碼在源工程的./Command/Shield.h文件中,這個(gè)放到后面的“自我保護(hù)”功能中講解)然后初始化套接字InitSocket,緊接著StartSniffer,然后就調(diào)用了WSACleanup開(kāi)始做清理工作了,所以我們就來(lái)專注分析StartSniffer函數(shù)(函數(shù)的實(shí)現(xiàn)代碼在源工程./Sniffer/Sniffer.h文件中)。 這里首先建立了一個(gè)IPPROTO_IP類型的原始套接字,緊接著調(diào)用函數(shù)GetInetIP獲取本機(jī)的IP地址,它這個(gè)GetInetIP函數(shù)中對(duì)各種情況都進(jìn)行了比較完善的考慮,大家在做自己的程序時(shí)可以參考一下。我們繼續(xù)關(guān)注它的sniffer工作,在bind了套接字之后調(diào)用了WSAIoctl將第二個(gè)參數(shù)dwIoControlCode設(shè)置為SIO_RCVALL來(lái)捕獲流經(jīng)本機(jī)的所有數(shù)據(jù);每捕獲到一個(gè)數(shù)據(jù)包后就調(diào)用自寫函數(shù)DecodeIPPack(具體功能后面有分析)將其解析出來(lái)后創(chuàng)建一個(gè)StartBackDoor線程,因?yàn)榻o它傳遞的參數(shù)為NULL,所以此線程函數(shù)將執(zhí)行BindShell函數(shù)(實(shí)現(xiàn)代碼在./Socket/Socket.h文件中)建立一個(gè)新的監(jiān)聽(tīng)套接字,將其屬性設(shè)置為可重用,每監(jiān)聽(tīng)到一個(gè)新的連接后就為其建立一個(gè)會(huì)話套接字并比較源IP,代碼如下:
這一段的作用比較容易讓人感到迷惑,AccpetAddr是接收到的連接另一方屬性,我們使用EditPlus的“在文件中查找”在整個(gè)目錄里面搜索SourceIP查看它到底是做什么的。最后把注意力放在了DecodeIPPack函數(shù)上(實(shí)現(xiàn)代碼在./Sniffer/Sniffer.h文件中):
在前面我們提到了這個(gè)函數(shù),但并不知道它的具體作用,現(xiàn)在就來(lái)詳細(xì)分析一下,每當(dāng)捕獲到一個(gè)數(shù)據(jù)包就傳遞給這個(gè)函數(shù),并將其強(qiáng)制轉(zhuǎn)換成IPHeader類型(這個(gè)結(jié)構(gòu)類型會(huì)經(jīng)常用到,網(wǎng)上有很多,附帶的源代碼中是定義在Sniffer.h文件中)。函數(shù)首先檢查數(shù)據(jù)報(bào)的協(xié)議類型是否為IPPROTO_TCP,然后將sourceIP字段值賦給SourceAddr.sin_addr.s_addr,再通過(guò)memcpy函數(shù)拷貝到SourceIP變量中,到這里我們可以知道每一個(gè)協(xié)議為IPPROTO_TCP的數(shù)據(jù)包的源IP都會(huì)被賦給SourceIP,隨后將其傳遞給了DecodeTCPPack和CheckTcpData函數(shù),在這兩個(gè)函數(shù)中先進(jìn)行初始化處理后就調(diào)用CheckTcpData檢查數(shù)據(jù),這個(gè)函數(shù)有一點(diǎn)點(diǎn)長(zhǎng),所以我就簡(jiǎn)單介紹一下它的工作流程算了:首先在數(shù)據(jù)報(bào)中找到"\n",接著判斷它前面是否為"\r",如果是就把它前面的內(nèi)容全部拷貝到一個(gè)字符串StringData中,再使用PortPoint = strstr(StringData,":");和HostPoint = strstr(StringData,"|");這兩句在里面尋找主機(jī)地址和端口,緊接著還會(huì)分析端口合法性和主機(jī)地址的有效性,這里就不多說(shuō)了。從這里可以知道它是使用嗅探的原理來(lái)取得控制端的IP實(shí)現(xiàn)反向連接的,大概原理就是捕獲流經(jīng)本機(jī)的所有數(shù)據(jù)包,然后根據(jù)自定義的協(xié)議來(lái)分析是否是控制端發(fā)送過(guò)來(lái)的數(shù)據(jù),如果是就從中取得相關(guān)信息后連接。 好了,中間分析了這么多后我們回到stricmp(SourceIP,inet_ntoa(AccpetAddr.sin_addr))這里繼續(xù)看,通過(guò)上面的分析我們清楚了SourceIP是用來(lái)區(qū)分是否是控制端的IP的。如果符合規(guī)則的話就為其建立一個(gè)控制線程,在此線程函數(shù)ClientThread中使用自定義函數(shù)ReveiceMessage來(lái)接收命令,首先判斷輸入的密碼是否正確,通過(guò)后即發(fā)送預(yù)定義的歡迎信息,然后進(jìn)入一個(gè)循環(huán)中不停地接受控制端的命令并執(zhí)行。 到這里我們就基本上把NameLess的連接流程搞清楚了,這種使用嗅探的方法有它的好處,就是容易過(guò)防火墻,但也有它的缺點(diǎn),就是當(dāng)網(wǎng)絡(luò)繁忙的時(shí)候很容易丟失封包。一些其他的反向連接方式更加流行,就是通過(guò)一個(gè)固定的域名來(lái)作為中轉(zhuǎn)站,控制端每次啟動(dòng)的時(shí)候都自動(dòng)將自己的IP更新到一個(gè)指定的網(wǎng)頁(yè)文件中,而服務(wù)端就通過(guò)讀取這個(gè)文件來(lái)得到控制端的IP后主動(dòng)進(jìn)行連接。網(wǎng)上的資料很多,大家可以多找來(lái)一些代碼參考。 本文出自:億恩科技【mszdt.com】 服務(wù)器租用/服務(wù)器托管中國(guó)五強(qiáng)!虛擬主機(jī)域名注冊(cè)頂級(jí)提供商!15年品質(zhì)保障!--億恩科技[ENKJ.COM] |