大数跨境
0
0

给银狐远控增加一个小功能01

给银狐远控增加一个小功能01 CppGuide
2026-01-06
0

引子

最近在研究摩纳哥远控的时候,发现摩纳哥生成的被控端带有小图标功能,点击启动会自动请求管理员权限运行。如下图所示:


研究了一下它的生成逻辑,发现实现原理是生成的被控模板文件使用manifest文件,在manifest文件中指定了程序运行时申请管理员权限。

于是打算给我维护的银狐远控也增加一个可以生成运行时主动请求管理员权限的被控exe功能,这样某些情况下就不需要每次手动选择使用管理员权限运行被控了。

特别申明:

本文内容仅限于用作技术交流,请勿使用本文介绍的技术做任何其他用途,否则后果自负,与本号无关。

图片


实现原理

下面详细讲一讲实现方法,当然本着授人以鱼不如授人以渔的精神,先讲一下技术原理。

要想一个exe程序运行时主动申请管理员权限,可以在该exe所在的Visual Studio工程中新增一种叫RT_MANIFEST的资源类型,然后导入一个xml文件,即所谓的manifest文件。如下图所示:

这个manifest文件内容如下:

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level='requireAdministrator' uiAccess='false' />
      </requestedPrivileges>
    </security>
  </trustInfo>
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*' />
    </dependentAssembly>
  </dependency>
</assembly>

代码中<requestedExecutionLevel level='requireAdministrator' uiAccess='false' />即设置请求管理员权限。

这个技术在《Windows核心编程》一书中4.5章节有详细的介绍。有兴趣的同学可以阅读一下,另外,我本人是搞安全工程的学生,机缘巧合认识小方老师,如果想从事Windows安全领域,这本《Windows核心编程》一书一定要认真阅读一下。

这里温馨提示一下,虽然如今的AI编程已经大大便利了程序员们的开发工作,但成体系的技术能力仍然是不可多得的核心竞争力,所以对于想进入这一行业,不能光靠AI搜索,该系统地学还得系统地学

另外,随着AI编程的兴起,Stackoverflow、CSDN等技术博客的访问量也受到很大的影响。但不意味着,这些网站对广大程序员不重要了,因为AI编程并不是原生创造,而是以这些技术站点搜索的内容为蓝本,进行智能整合,试想某一天,Stackoverflow、CSDN等这些站点关闭或者禁止AI机器人对其内容进行检索,这些所谓的AI编程也会因为缺少搜索来源而缺少语料,进而影响编程结果。

回到主题上来,我们给银狐增加一种新的类型的exe,同时要保留原来生成普通exe的能力,一种解决方案就是新增一个嵌入了manifest文件的exe模板,利用这个模板来生成。但是这样太麻烦了,且会造成大量冗余代码。

所以,我们换个思路:在原来生成exe的逻辑中新增一个选项参数,如果生成的是新类型的exe,就传递这个参数,否则就使用默认参数生成原来的普通exe。

当传递了这个参数之后,在生成普通exe文件完成之后,我们再动态地将manifest文件嵌入其中。实现代码如下:

bool CBuildDlg::InjectManifest(const wchar_t* exePath)
{
    const char manifest[] =
        "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>"
        "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">"
        "<assemblyIdentity version=\"1.0.0.0\" processorArchitecture=\"*\" "
        "name=\"RuntimeInjectedApp\" type=\"win32\"/>"
        "<trustInfo xmlns=\"urn:schemas-microsoft-com:asm.v3\">"
        "<security><requestedPrivileges>"
        "<requestedExecutionLevel level=\"requireAdministrator\" uiAccess=\"false\"/>"
        "</requestedPrivileges></security></trustInfo>"
        "</assembly>";

    HANDLE hUpdate = BeginUpdateResourceW(exePath, FALSE);
    if (!hUpdate)
        returnfalse;

    BOOL ok = UpdateResourceW(
        hUpdate,
        RT_MANIFEST, // 资源类型是RT_MANIFEST
        MAKEINTRESOURCEW(1),   // ID = 1(标准)
        MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
        (LPVOID)manifest,
        sizeof(manifest) - 1
    );

    if (!ok)
    {
        EndUpdateResourceW(hUpdate, TRUE);
        returnfalse;
    }

    return EndUpdateResourceW(hUpdate, FALSE);
}

外层调用:

BOOL CBuildDlg::ChangeDataAndWriteFile(const CString& strPath, BOOL bChangeExport, bool withRequestAdmin/* = false*/)
{
    
    // ...省略无关代码...

    //写出配置好的文件
    CFile file;
    if (file.Open(m_szWritePath, CFile::modeCreate | CFile::modeWrite | CFile::modeRead | CFile::typeBinary))
    {
        if (dwOffset != -1)
            memcpy(str + dwOffset, (char*)&m_szConfig, lstrlen(m_szConfig) * 2 + 1);

        if (bChangeExport)
            memcpy(str + dwOffset_export, (char*)exportnamebuf, exportnamelen);
        file.Write(str, len);
        file.Close();
        m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)_T("写出成功"));  m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)m_szWritePath);  m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)_T("\r\n"));
        SAFE_DELETE_AR(str);

        // 生成新类型的exe时withRequestAdmin=true
        if (withRequestAdmin)
        {
            return InjectManifest(m_szWritePath);
        }

        return TRUE;
    }
    else
    {
        m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)_T("文件无法创建,查看是否占用\r\n"));
        m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)m_szWritePath);
        m_edit_tip.SendMessage(EM_REPLACESEL, 0, (LPARAM)_T("r\n"));
        SAFE_DELETE_AR(str);
        return FALSE;
    }

}

然后再在主控生成界面加一个新类型exe生成按钮,为了便于区分,我们给这两个按钮都加上人性化的tooltip提示,效果如下:

对比一下生成的普通被控exe,新的类型的exe生成时就带有盾牌图标且运行时自动请求管理员权限了。来看下效果:

好了,本篇内容到此就结束了,感谢您的阅读。


源码获取

如果对银狐(winos)有兴趣,可以通过下面的方式获取全套源码:

关注后回复【winos】即可获取源码


推荐阅读

银狐远控问题排查与修复——Viusal Studio集成Google Address Sanitizer排查内存问题
银狐远控代码中差异屏幕bug修复
银狐远程屏幕内存优化方法探究
银狐远程软件bug修复记录 第03篇

银狐远程软件 UDP 断线无法重连的bug排查和修复

银狐远程软件代理映射功能优化思路分享

银狐远程软件去后门方法

银狐远控一键编译调试与开发教程

银狐远控免杀与shellcode修复思路分析 01

银狐ShellCode混淆怪招

详解银狐远控源码中那些C++编码问题


推荐课程

如果你想获得开发银狐远控这样中大型C/C++的能力,可以考虑隔壁张小方老师的《C/C++项目实战训练营》,训练营中详细地拆解三个中大型C/C++项目源码,再从零带着手写三个C/C++项目。相比较动辄几千几万块的线上课程和培训班,这个是近年来学习C/C++开发能力性价比最高的课程之一。

笔者本人是搞安全工程的学生,也是这个训练营的学员之一,给大家推荐一下。

训练营链接:

C/C++ 项目实战训练营 详细目录

【声明】内容源于网络
0
0
CppGuide
专注于高质量高性能C++开发,站点:cppguide.cn
内容 981
粉丝 0
CppGuide 专注于高质量高性能C++开发,站点:cppguide.cn
总阅读2
粉丝0
内容981