VM

KraZz

(L3) cache
Пользователь
Регистрация
18.06.2009
Сообщения
196
Реакции
7
Так как не известно, будет ли вообще юзаться ВМ в лоадере, решил вынести обсуждение тех. Аспектов в отдельный топ.
http://demonteam.narod.ru/private/g1m7nodq.rar
PASS: yq7srg8xt56
ВМ которую будем обсуждать, и которая будет использоваться для примера, чтобы проще было понять, о чем будет дальше речь, находится в архиве в файле VM.exe.trojan
Также в архив добавил паблик исходники одной ВМ, очень уж похоже на то, что эти сорцы стали базой для этой ВМ (хотя я не уверен, но это не суть и важно, лишними они точно не будут)
В этой ВМ (VM.exe.trojan) используется вместо байт-кода word-код
Ключевой момент этой ВМ скрывается вот в этом участке кода:
Код:
004511DA 0F B7 07                movzx   eax, word ptr [edi]
004511DD 8B D0                   mov     edx, eax
004511DF C1 EA 0C                shr     edx, 0Ch
004511E2 25 FF 0F 00 00          and     eax, 0FFFh
004511E7 03 45 04                add     eax, [ebp+4]
В тоже время это и есть слабое место этой ВМ, если не вдаваться в подробности, то такую ВМ аверы "порвут" и даже не заметят. (ИМХО)
Из word`а получаем оффсет на "что-то" и ID исполнителя word-кода
Код:
TODO: место, где сравнивается ID исполнителя word-кода
004511F4 80 FA 01                cmp     dl, 1
004511F7 75 07                   jnz     short loc_451200
TODO: исполнитель word-кода
004511F9 8B 10                   mov     edx, [eax]
004511FB 89 55 FC                mov     [ebp-4], edx
004511FE EB 68                   jmp     short LNEXT
====================================
TODO: место, где сравнивается ID исполнителя word-кода
loc_451200:
00451200 80 FA 02                cmp     dl, 2
00451203 75 05                   jnz     short loc_45120A
TODO: исполнитель word-кода
00451205 89 45 FC                mov     [ebp-4], eax
00451208 EB 5E                   jmp     short LNEXT
====================================
loc_45120A:
[...]
Если посмотреть исполнителей word-кода около десятка, и сама ВМ очень проста и примитивна
Нам же нужно вместо этого кода:
Код:
004511DA 0F B7 07                movzx   eax, word ptr [edi]
004511DD 8B D0                   mov     edx, eax
004511DF C1 EA 0C                shr     edx, 0Ch
004511E2 25 FF 0F 00 00          and     eax, 0FFFh
004511E7 03 45 04                add     eax, [ebp+4]
Вставить какую-нибудь "математическую формулу", которая на выходе будет строить график, а на входе будет принимать результат этой формулы (возможно немного подкорректированный исполнителем).
Хз. может и нихера и непонятно выразился, в процессе обсуждения думаю, разберемся, что да как...
Скорее всего, нарисую диаграмму или что-то в этом духе, пока думаю, нужно всем просто ознакомицца с файлами из архива и сказать че кто думает, или если что-то не понятно задать вопросы...
 
По теме. Можно заюзать в лоадере для критичных участков

Код:
/* Original code by: abhe
   Ported by: steve10120@ic0de.org
   Thanks to Edi for help with inst_table
*/

#include <Windows.h>
#include <iostream>

int const REGISTER_EAX = 0; 
int const REGISTER_ECX = 1; 
int const REGISTER_EDX = 2; 
int const REGISTER_EBX = 3; 
int const REGISTER_ESP = 4; 
int const REGISTER_EBP = 5; 
int const REGISTER_ESI = 6; 
int const REGISTER_EDI = 7; 
int const REGISTER_NOP = 8; 

typedef struct _VMCONTEXT
{
    DWORD EIP;
    DWORD Reg[8];
} VMCONTEXT, *PVMCONTEXT;

typedef void (VM_FUNCTION_CALL)(PVMCONTEXT c);

typedef struct _INST
{
    VM_FUNCTION_CALL* FunctionCall;
} INST, *PINST;

void AddCode(PVMCONTEXT c, BYTE n)
{
    c->EIP += n;
}

void VRetn(PVMCONTEXT c)
{
}

void VJmp(PVMCONTEXT c)
{
    DWORD imm32; 

    c->EIP++;
    imm32 = *(PDWORD)c->EIP;
    c->EIP = imm32;
}

void VPUSHImm(PVMCONTEXT c)
{
    DWORD imm32;

    c->EIP++;
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    *(PDWORD)c->Reg[REGISTER_ESP] = imm32;
    c->Reg[REGISTER_ESP] += 4;
}

void VPUSHReg(PVMCONTEXT c)
{
    BYTE regflag;
    DWORD imm32;

    c->EIP++;
    regflag = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( regflag < 8 )
    {
        imm32 = c->Reg[regflag];
        *(PDWORD)c->Reg[REGISTER_ESP] = imm32;
        c->Reg[REGISTER_ESP] += 4;
    }
}

void VPUSHMem(PVMCONTEXT c)
{
    DWORD mem32;
    DWORD imm32;

    c->EIP++;
    mem32 = *(PDWORD)c->EIP;
    imm32 = *(PDWORD)mem32;
    AddCode(c, 4);
    *(PDWORD)c->Reg[REGISTER_ESP] = imm32;
    c->Reg[REGISTER_ESP] += 4;
}

void VPOPReg(PVMCONTEXT c)
{
    BYTE regflag;
    DWORD imm32;

    c->EIP++;
    regflag = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( regflag < 8 ) 
    {
        imm32 = *(PDWORD)c->Reg[REGISTER_ESP];
        c->Reg[REGISTER_ESP] -= 4;
        c->Reg[regflag] = imm32;
    }
}

void VPOPMem(PVMCONTEXT c)
{
    DWORD imm32;
    DWORD mem32;

    imm32 = *(PDWORD)c->Reg[REGISTER_ESP];
    c->Reg[REGISTER_ESP] -= 4;
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    *(PDWORD)mem32 = imm32;
}

void VMovRegReg(PVMCONTEXT c)
{
    BYTE DestReg, SrcReg;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
        c->Reg[DestReg] = c->Reg[SrcReg];
}

void VMovRegImm(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD imm32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] = imm32;
}

void VMovRegMem(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD mem32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] = *(PDWORD)mem32;
}

void VADDRegReg(PVMCONTEXT c)
{
    BYTE DestReg, SrcReg;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
        c->Reg[DestReg] += c->Reg[SrcReg];
}

void VADDRegImm(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD imm32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] += imm32;
}

void VADDRegMem(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD mem32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] += *(PDWORD)mem32;
}

void VSUBRegReg(PVMCONTEXT c)
{
    BYTE DestReg, SrcReg;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
        c->Reg[DestReg] -= c->Reg[SrcReg];
}

void VSUBRegImm(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD imm32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] -= imm32;
}

void VSUBRegMem(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD mem32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if ( DestReg < 8 )
        c->Reg[DestReg] -= *(PDWORD)mem32;
}

void VMulEaxReg(PVMCONTEXT c)
{
    BYTE SrcReg;

    c->EIP++;
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( SrcReg < 8 )
        c->Reg[REGISTER_EAX] *= c->Reg[SrcReg];
}

void VDivEaxReg(PVMCONTEXT c)
{
    BYTE SrcReg;

    c->EIP++;
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( SrcReg < 8 )
    {
        c->Reg[REGISTER_EAX] /= c->Reg[SrcReg];
        c->Reg[REGISTER_EAX] %= c->Reg[SrcReg];
    }
}

void VANDRegReg(PVMCONTEXT c)
{
    BYTE DestReg, SrcReg;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( ( DestReg < 8 ) && ( SrcReg < 8 ) )
        c->Reg[DestReg] &= c->Reg[SrcReg];
}

void VAndRegImm(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD imm32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if (DestReg < 8 )
        c->Reg[DestReg] &= imm32;
}

void VAndRegMem(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD mem32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if (DestReg < 8 )
        c->Reg[DestReg] &= *(PDWORD)mem32;
}

void VORRegReg(PVMCONTEXT c)
{
    BYTE DestReg, SrcReg;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    SrcReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    if ( ( DestReg < 8 ) & ( SrcReg < 8 ) )
        c->Reg[DestReg] |= c->Reg[SrcReg];
}

void VORRegImm(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD imm32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    imm32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if (DestReg < 8 )
        c->Reg[DestReg] |= imm32;
}

void VORRegMem(PVMCONTEXT c)
{
    BYTE DestReg;
    DWORD mem32;

    c->EIP++;
    DestReg = *(PBYTE)c->EIP;
    AddCode(c, 1);
    mem32 = *(PDWORD)c->EIP;
    AddCode(c, 4);
    if (DestReg < 8 )
        c->Reg[DestReg] |= *(PDWORD)mem32;
}

const INST inst_table[23] = {{VRetn},{VJmp},{VPUSHImm},{VPUSHReg},{VPUSHMem},{VPOPReg},{VPOPMem},{VMovRegReg},
{VMovRegImm},{VMovRegMem},{VADDRegReg},{VADDRegImm},{VADDRegMem},{VSUBRegReg},{VSUBRegImm},{VSUBRegMem},
{VMulEaxReg},{VDivEaxReg},{VANDRegReg},{VAndRegImm},{VORRegReg},{VORRegImm},{VORRegMem}};

VMCONTEXT ExecuteVM(LPVOID Code, DWORD Size)
{
    INST Ins;
    BYTE Op;
    LPVOID Stack;
    VMCONTEXT Context;

    for (Op = 0; Op < 7; Op++)
        Context.Reg[Op] = 0;

    Stack = GlobalAlloc(GMEM_FIXED, 1024 * 1024 * 2);
    if (Stack)
    {
        Context.Reg[REGISTER_ESP] = (DWORD)Stack;
        Context.EIP = (DWORD)Code;
        while (Context.EIP <= ((DWORD)Code + Size - 1)) 
        {
            Op = *(PBYTE)Context.EIP;    
            Ins = inst_table[Op];
            Ins.FunctionCall(&Context);
            if (Op == 0)
                break;
        }
        GlobalFree(Stack);
    }
    return Context;
}

int main(void)
{
    BYTE Code[13] = {
    	0x08,0x00,0x05,0x00,0x00,0x00, // mov eax, 5
                    0x0B,0x00,0x05,0x00,0x00,0x00, // add eax, 5
                    0x00
    	};        // retn
    
    VMCONTEXT Context = ExecuteVM(&Code, sizeof(Code));
    std::cout << Context.Reg[REGISTER_EAX] << std::endl;
    return 0;
}
 
такс.. виртуализация...
с одной стороны это мощная технология для зАаааатруднения реверса кода, но с другой стороны скрывать под вм код, качающий бинарь с вэба, будь то урлдаун, интернетопенетц.... или вариант через оле, смысл в том что на конце перехватывается сформированная ссылка.
другой компот, когда в боте будет алгоритм генерации доменов (хотя и он нах нужен? лучше использовать более инновационные мысли).

p.s. короче если вм обсужается как технология в персептиве, то да, это отлично, интересно будет разобраться в теме глубже, если на данный момент с мин. функционалом лодыря, то пока не нужно.
p.s.s. есть наработки в этой теме, не мою, но кода довольно много, и не плохого такого. найду выложу.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх