|
|
|
This is the SVDL language in BNF modified format (I use parameter for specify the dimension of a argument):
svdl ::= CODE 01; block
block ::= instruction IF bool_esp + string
instruction(i) ::= {
IF bool_esp - |
identifier(i) := ext_esp ;
}
bool_esp ::= ( identifier(i) | read(i) )
( < | <= | = | > | >= | <> )
( identifier(i) | constant(i) | string(i) )
identifier(byte) ::= (( | | @ ) letter % ) |
letter #
identifier(word) ::= letter %
letter ::= A | ... | Z
constant(byte) ::= ' char ' |
number(byte)
constant(word) ::= ' char char ' |
number(word)
read(word >word) ::= [ number(byte) +] |
[ identifier +]
read(byte) ::= [ number(byte) ] |
[ identifier ] |
[_ number(byte)] |
[_ identifier ] |
ext_esp(byte) ::= ext_esp_(byte)
ext_esp(word) ::= ext_esp_(word) |
TIME | DATE | ATTR | DIML | DIMH
ext_esp_(i) ::= read(i) | INC | DEC |
identifier(i) |
identifier(i)
( ADC | ADD | AND | DIV |
IDIV | IMUL | MUL | OR |
ROL | ROR | SAR | SBB |
SHL | SAL | SHR | SUB |
XOR )
identifier(i)
string ::= ' { char } '
char ::= an ascii char
number(i) ::= hex number of type i
comment ::= { string }
The SVDL is a language that is based on machine 8086 language. A SVDL variable is
simple an alphabet letter: A, B, ... Z.
Due to the machine language corresponding, we must always specify it's dimension:
X# a byte variable X% a word variableSo, X# must be think like BL register, while X% must be think like AX register. But in 8086, AX may be divided in AL and AH, so in SVDL a word variable can be divided too:
|X% a low byte of word variable @X% a high byte of word variableAt one variable we can assign other thing of the same type like:
C#:=45; an byte hex number C#:=|B%; the low part of word variable D%:= A% XOR B%; an xor of two word variable X#:='d'; a charNote that a word assignment is like in 8086 endian type: low, high.
C#:=[12]; a disk byte read from position 12h of file C%:=[12+]; a disk bytes read from position 12h of file C#:=[_12h]; a disk byte read from end position 12h of file C#:=[A#]; a disk byte read from position given by A# of file C#:=[_A#]; a disk byte read from end position given by A# of fileNote that a read with word variables has two implementation: if variables is from A to L the jump is up to 2 at pow of 16, while if they are from M to Z the jump is up to 2 at pow of 32, because:
C#:=[M%]; the jump is to the 32 bit number given by N%:M%This is useful for file that has a size upper than 64KB.
Other special instruction can be assigned to a variables:
C%:=DATE; gives the DOS file date C%:=DIML; gives the low dimension of the file C%:=DIMH; gives the high dimension of the file C%:=ATTR; gives the DOS attribute of the file C%:=TIME; gives the DOS file timeThe SVDL has a particular implementation of a IF instruction: a IF without the ELSE part. In fact, if one IF give false, this means that the virus don't have infect this file, so the SVDL program terminate. In a IF instruction we can compare variables with other variables (of the same type), or information from file:
IF A%>=B% - compares if A is greater or equal that B IF [00+]='string' - compares if file from position 0 has stringIf a IF has a + instead of - this means that a true comparison terminate the SVDL programs showing the string after +:
IF A#=@B% + 'virus found'Note that a SVDL programs start with the instruction CODE. CODE specify the actual version of SVDL.
Here there's the SVDL for detecting the Dark Avenger virus in an EXE program:
CODE 01;
IF [00+]='ZM'
- A%:=[08+]; {header paragraphs}
B%:=[16+]; {initial CS}
A%:=A% ADD B%;
D%:=10;
Z%:=0;
A%:=A% MUL D%;
B%:=[14+]; {initial IP}
A%:=A% ADD B%;
C%:=0;
Z%:=Z% ADC C%; {address Z%:A%}
D%:=68;
A%:=A% SUB D%;
E%:=Z% SBB C%; {virus moves pointer to E%:A%, not needed here}
F%:=708;
A%:=A% ADD F%;
E%:=E% ADC C%;
L%:=DIML;
H%:=DIMH;
IF L%=A% -
IF H%=E% + 'DarkAvenger (EXE)'
{the virus now compares if there's it's body from the position of file pointer}
The below is the SVDL program that detects the FLIP virus. Flip use a little
sophisticated encryptios technique to mask itself.
CODE 01;
IF [_47]=0E {PUSH CS }
- IF [_46]=0BB {MOV BX,..}
- IF [_43]=1F {POP DS }
- IF [_42]=0B9 {MOV CX,..}
- IF [_3F]=0B2 {MOV DL,..}
- IF [_3D]=81 {ADD ... }
- IF [_3C]=0C1 {... CX,..}
- IF [_39]=0EB {JMP ... }
- A#:=[_38];
B#:=37;
B#:=B# SUB A#;
IF [_B#]=00 {ADD ...}
- B#:=DEC;
IF [_B#]=97 {... [BX],DL}
- C#:=3;
B#:=B# SUB C#;
IF [_B#]=43 {INC BX}
- B#:=DEC;
IF [_B#]=0EB {JMP ...}
- B#:=DEC;
A#:=[_B#];
B#:=DEC;
B#:=B# SUB A#;
IF [_B#]=0E2 {LOOP ...}
- B#:=DEC;
B#:=DEC;
IF [_B#]=0E9 {JMP ...}
+ 'FLIP (COM-EXE)'
| PC |