作者 | 修订时间 |
---|---|
2024-01-13 04:55:28 |
fscan免杀
前言
首次学习免杀,利用dll劫持的方式,利用微软的白名单机制,实现免杀。本章节代码已同步至github,项目地址: fscan
过程
准备fscan的源码。
git clone https://github.com/shadow1ng/fscan.git
将fsacn的源码中的main.go文件中的main函数如下,由于init
函数,在go语言中,为包首次调用的时候会被执行;Go 编写的 DLL 被 C 程序调用时,init
函数会在 DLL 加载到内存时执行,而 main
函数通常不适用于 DLL 并且不会被执行。
package main
import "C"
import (
"fmt"
"time"
"github.com/shadow1ng/fscan/Plugins"
"github.com/shadow1ng/fscan/common"
)
//export DllCanUnloadNow
func DllCanUnloadNow() {}
//export DllGetClassObject
func DllGetClassObject() {}
//export DllRegisterServer
func DllRegisterServer() {}
//export DllUnregisterServer
func DllUnregisterServer() {}
func init() {
start := time.Now()
var Info common.HostInfo
common.Flag(&Info)
common.Parse(&Info)
Plugins.Scan(Info)
t := time.Now().Sub(start)
fmt.Printf("[*] 扫描结束,耗时: %s\n", t)
}
func main(){}
编译 windows amd64
下的 dll
GOOS=windows GOARCH=amd64 CGO_ENABLED=1
go build -buildmode=c-shared -o fscan.dll ./cmd/fscan_dll/main.go
这里可以选择 c
和go
加载器,c
加载器的代码如下:
// gcc -o fscan_load fscan_load.c
#include <stdio.h>
#include <windows.h>
int main() {
HMODULE hDLL;
hDLL = LoadLibrary("fscan.dll");
if (hDLL != NULL) {
// 定义函数指针类型
typedef void (*FunctionType)();
// 为每个导出函数创建一个函数指针
FunctionType DllCanUnloadNow = (FunctionType)GetProcAddress(hDLL, "DllCanUnloadNow");
FunctionType DllGetClassObject = (FunctionType)GetProcAddress(hDLL, "DllGetClassObject");
FunctionType DllRegisterServer = (FunctionType)GetProcAddress(hDLL, "DllRegisterServer");
FunctionType DllUnregisterServer = (FunctionType)GetProcAddress(hDLL, "DllUnregisterServer");
// 调用每个函数(如果函数指针非空)
if (DllCanUnloadNow) DllCanUnloadNow();
if (DllGetClassObject) DllGetClassObject();
if (DllRegisterServer) DllRegisterServer();
if (DllUnregisterServer) DllUnregisterServer();
// 卸载 DLL
FreeLibrary(hDLL);
printf("All functions executed successfully.\n");
}
else {
printf("Failed to load DLL.\n");
}
return 0;
}
编写dll
加载器,dll
加载器的作用是将dll
加载到内存中,然后调用dll
中的init
函数,实现免杀。
// gradle build -o fscan_loader_go.exe main.go
package main
import (
"fmt"
"syscall"
)
func main() {
dll, err := syscall.LoadLibrary("fscan_go.dll")
if err != nil {
fmt.Printf("[-] Failed to load DLL: %s\n", err)
return
}
defer func(handle syscall.Handle) {
err := syscall.FreeLibrary(handle)
if err != nil {
fmt.Printf("[-] Failed to free DLL: %s\n", err)
}
}(dll)
// 定义并尝试获取 DLL 中的函数
dllCanUnloadNow, err := syscall.GetProcAddress(dll, "DllCanUnloadNow")
// 判断err == nil 并且 dllCanUnloadNow != 0
if err == nil && dllCanUnloadNow != 0 {
_, _, err := syscall.SyscallN(dllCanUnloadNow, 0, 0, 0, 0)
if err != 0 {
fmt.Printf("[-] Failed to execute DllCanUnloadNow: %s\n", err)
}
}
dllGetClassObject, err := syscall.GetProcAddress(dll, "DllGetClassObject")
if err == nil && dllGetClassObject != 0 {
_, _, err := syscall.SyscallN(dllGetClassObject, 0, 0, 0, 0)
if err != 0 {
fmt.Printf("[-] Failed to execute DllGetClassObject: %s\n", err)
}
}
dllRegisterServer, err := syscall.GetProcAddress(dll, "DllRegisterServer")
if err == nil && dllRegisterServer != 0 {
_, _, err := syscall.SyscallN(dllRegisterServer, 0, 0, 0, 0)
if err != 0 {
fmt.Printf("[-] Failed to execute DllRegisterServer: %s\n", err)
}
}
dllUnregisterServer, err := syscall.GetProcAddress(dll, "DllUnregisterServer")
if err == nil && dllUnregisterServer != 0 {
_, _, err := syscall.SyscallN(dllUnregisterServer, 0, 0, 0, 0)
if err != 0 {
fmt.Printf("[-] Failed to execute DllUnregisterServer: %s\n", err)
}
}
fmt.Println("All functions executed successfully.")
}
使用go语言编译加载器, 需要使用gradle进行混淆,防止被杀软查杀。
go install mvdan.cc/garble@latest
GOOS=windows GOARCH=amd64 CGO_ENABLED=1
gradle build -o fscan_loader.exe ./cmd/fscan_loader/main.go
将fscan.dll
和fscan_loader.exe
放在同一目录下,运行fscan_loader.exe
,即可实现免杀。
# 改个名字
mv fscan_loader.exe system_dll.exe
./system_dll.exe
结果
- 火绒
- 微步云沙箱