go学习-001
沙箱是一个比较吊毛和比较讨人厌的东西(吐槽完毕)。是用于隔离正在运行的程序的安全机制。这个程序代码可能来自未经验证的或不受信任的第三方、供应商、用户或网站,而不会危害主机或操作系统。
这边搜集一些反沙箱调试的思路,配合写出一些代码
基于go语言
1、操作系统语言检测
沙箱大部分都是国外的英文,所以根据首选项操作系统来判断操作系统语言是不是中文来判断(但是)。使用golang.org/x/sys/windows包。
代码如下:
package src
import (
"fmt"
"golang.org/x/sys/windows"
"os"
)
func CheckLanguage() { // 首字母大写,成为导出的函数
a, err := windows.GetUserPreferredUILanguages(windows.MUI_LANGUAGE_NAME)
if err != nil {
fmt.Println("Error:", err)
os.Exit(1)
}
if a[0] != "zh-CN" {
fmt.Println("英文环境")
os.Exit(1)
} else {
fmt.Println("中文环境")
}
}
2、操作系统信息
执行wmic命令,返回操作系统信息,根据关键字来判断,也是略简单粗暴。但是这里会被沙箱直接检测到所以我们这边要做一下他的一些免杀,需要更改一些他的命令
package src
import (
"os/exec"
"strings"
)
func Check_Virtual() (bool, error) {
// 检查计算机模型信息
cmd := exec.Command("cmd", "/C", "wmic path Win32_ComputerSystem get Model")
stdout, err := cmd.Output()
if err != nil {
return false, err
}
model := strings.ToLower(string(stdout))
// 检查BIOS信息
cmd = exec.Command("cmd", "/C", "wmic bios get serialnumber")
biosOutput, err := cmd.Output()
if err != nil {
return false, err
}
bios := strings.ToLower(string(biosOutput))
// 检查硬盘驱动器信息
cmd = exec.Command("cmd", "/C", "wmic diskdrive get model")
diskOutput, err := cmd.Output()
if err != nil {
return false, err
}
disk := strings.ToLower(string(diskOutput))
// 增加更多判断条件,如检测常见虚拟机厂商的标识
if strings.Contains(model, "virtual") || strings.Contains(model, "vmware") || strings.Contains(model, "kvm") || strings.Contains(model, "virtualbox") ||
strings.Contains(bios, "virtual") || strings.Contains(bios, "vmware") || strings.Contains(disk, "vbox") || strings.Contains(disk, "virtual") {
return true, nil
}
return false, nil
}
3、检测系统文件
根据虚拟机或沙箱可能存在的一些文件,来进行判断。
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}
func fack(path string) {
b, _ := PathExists(path)
if b {
os.Exit(1)
}
}
func check_file() {
fack("C:\windows\System32\Drivers\Vmmouse.sys")
fack("C:\windows\System32\Drivers\vmtray.dll")
fack("C:\windows\System32\Drivers\VMToolsHook.dll")
fack("C:\windows\System32\Drivers\vmmousever.dll")
fack("C:\windows\System32\Drivers\vmhgfs.dll")
fack("C:\windows\System32\Drivers\vmGuestLib.dll")
fack("C:\windows\System32\Drivers\VBoxMouse.sys")
fack("C:\windows\System32\Drivers\VBoxGuest.sys")
fack("C:\windows\System32\Drivers\VBoxSF.sys")
fack("C:\windows\System32\Drivers\VBoxVideo.sys")
fack("C:\windows\System32\vboxdisp.dll")
fack("C:\windows\System32\vboxhook.dll")
fack("C:\windows\System32\vboxoglerrorspu.dll")
fack("C:\windows\System32\vboxoglpassthroughspu.dll")
fack("C:\windows\System32\vboxservice.exe")
fack("C:\windows\System32\vboxtray.exe")
fack("C:\windows\System32\VBoxControl.exe")
}
4、延迟运行
我们这里就当一次老六,因为大部分的检测运行资源有限,可以延迟等一会再进行真实操作。(杀敌一千自损八百)
func timeSleep() (int, error) {
startTime := time.Now()
time.Sleep(5 * time.Second)
endTime := time.Now()
sleepTime := endTime.Sub(startTime)
if sleepTime >= time.Duration(5*time.Second) {
return 1, nil
} else {
return 0, nil
}
}
5、开机时间检测
因为沙箱检测完都会还原或者充值系统,因此可以通过检测开机事件来判断是否为真实的运行情况。
func bootTime() (int, error) {
var kernel = syscall.NewLazyDLL("Kernel32.dll")
GetTickCount := kernel.NewProc("GetTickCount")
r, _, _ := GetTickCount.Call()
if r == 0 {
return 0, nil
}
ms := time.Duration(r * 1000 * 1000)
tm := time.Duration(30 * time.Minute)
if ms < tm {
return 0, nil
} else {
return 1, nil
}
}
6、检测物理内存大小
就跟前面赌沙箱耗费资源多少一样,这里笃定大部分物理机内存都在4gb以上,通过判断大于4来认定为是物理机。
func physicalMemory() (int, error) {
var mod = syscall.NewLazyDLL("kernel32.dll")
var proc = mod.NewProc("GetPhysicallyInstalledSystemMemory")
var mem uint64
proc.Call(uintptr(unsafe.Pointer(&mem)))
mem = mem / 1048576
if mem < 4 {
return 0, nil
}
return 1, nil
}
7、检测cpu数目
跟前面一样,认定cpu数目大于4
func numberOfCPU() (int, error) {
a := runtime.NumCPU()
if a < 4 {
return 0, nil
} else {
return 1, nil
}
}
8、通过检测临时文件数目
正常的物理机中,用户日常的使用导致其肯定会再临时文件夹中存在一定数量的临时文件,因此临时文件夹内的文件数量可以被用来判定运行环境是否为沙箱。
func numberOfTempFiles() (int, error) {
conn := os.Getenv("temp")
var k int
if conn == "" {
return 0, nil
} else {
local_dir := conn
err := filepath.Walk(local_dir, func(filename string, fi os.FileInfo, err error) error {
if fi.IsDir() {
return nil
}
k++
return nil
})
if err != nil {
return 0, nil
}
}
if k < 30 {
return 0, nil
}
return 1, nil
}
9、查询硬盘大小
一些恶意程序使用系统硬盘大小作为判断是否运行在虚拟机中的依据,因为虚拟机的硬盘大小通常比较小。你可以通过 Windows API 获取系统硬盘的大小。
package main
import (
"fmt"
"syscall"
"unsafe"
)
func getDiskSize(path string) (uint64, error) {
var freeBytesAvailable, totalBytes, totalFreeBytes uint64
pathPtr, err := syscall.UTF16PtrFromString(path)
if err != nil {
return 0, err
}
kernel32 := syscall.NewLazyDLL("kernel32.dll")
getDiskFreeSpaceExW := kernel32.NewProc("GetDiskFreeSpaceExW")
_, _, err = getDiskFreeSpaceExW.Call(
uintptr(unsafe.Pointer(pathPtr)),
uintptr(unsafe.Pointer(&freeBytesAvailable)),
uintptr(unsafe.Pointer(&totalBytes)),
uintptr(unsafe.Pointer(&totalFreeBytes)),
)
if err != nil && err.Error() != "The operation completed successfully." {
return 0, err
}
return totalBytes, nil
}
func main() {
diskSize, err := getDiskSize("C:\\")
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Printf("Disk size: %d bytes\n", diskSize)
}
10、反逆向工程
检测内核调试器可以通过检查系统的调试标志来实现。以下是一个简单的示例,使用 NtQuerySystemInformation API 来检查系统是否启用了调试。
package main
import (
"fmt"
"syscall"
"unsafe"
)
const (
SystemBasicInformation = 0
)
type SYSTEM_BASIC_INFORMATION struct {
Reserved uint32
TimerResolution uint32
PageSize uint32
NumberOfPhysicalPages uint32
MinimumUserModeAddress uintptr
MaximumUserModeAddress uintptr
ActiveProcessorsAffinityMask uint32
NumberOfProcessors uint32
}
var (
modntdll = syscall.NewLazyDLL("ntdll.dll")
procNtQuerySystemInformation = modntdll.NewProc("NtQuerySystemInformation")
)
func isDebuggerPresent() bool {
var sysInfo SYSTEM_BASIC_INFORMATION
ret, _, _ := procNtQuerySystemInformation.Call(
uintptr(SystemBasicInformation),
uintptr(unsafe.Pointer(&sysInfo)),
uintptr(unsafe.Sizeof(sysInfo)),
0,
)
return ret == 0
}
func main() {
if isDebuggerPresent() {
fmt.Println("Debugger detected")
} else {
fmt.Println("No debugger detected")
}
}
11、静态文件特征
PE文件节的数量异常,可以使用 Go 的 pe 包来解析 PE 文件,并检查节的数量。这可以帮助检测 PE 文件是否被修改或加壳。
package main
import (
"debug/pe"
"fmt"
"os"
)
func checkPESections(filePath string) error {
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
f, err := pe.NewFile(file)
if err != nil {
return err
}
sectionCount := len(f.Sections)
fmt.Printf("Number of sections: %d\n", sectionCount)
if sectionCount > 10 {
fmt.Println("Warning: Abnormally high number of sections")
}
return nil
}
func main() {
err := checkPESections("path_to_your_pe_file.exe")
if err != nil {
fmt.Println("Error:", err)
}
}
博主真是太厉害了!!!
博主真是太厉害了!!!
叼茂SEO.bfbikes.com
想想你的文章写的特别好https://www.237fa.com/
不错不错,我喜欢看 https://www.ea55.com/
不错不错,我喜欢看 www.jiwenlaw.com
文章的确不错啊https://www.cscnn.com/
真好呢