Statistics

Members: 1925
News: 293
Web Links: 1
Visitors: 3811400

Who's Online

We have 2 guests online
Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home
List Scan Library Routine
User Rating: / 0
PoorBest 
Written by Laura Fairhead   


Firstly let me introduce an auxillary routine this uses. It is called 'scaws' and scans past white space. It is very simple, and the definition of whitespace here is SPACE (020h) or TAB (09h):-

 

 

========START OF CODE======================================================

;
;scaws- scan whitespace
;

;entry:     DS:SI=string
;           DF=0
;
;exit:      SI=updated to first non-whitespace character
;           AL=value of the character

;

scaws PROC NEAR

;
;there is nothing to explain here but you might take note now ;that I always use the same label names in different PROC blocks, ;in MASM you can do this with OPTION SCOPED ;

lop: LODSB

        CMP AL,020h
JZ lop
CMP AL,09h
JZ lop
DEC SI
RET

scaws ENDP

========END OF CODE========================================================

'scalst' is basically a routine to scan-convert a list which can consist of values and strings. The radix of the values must be set before hand by calling 'scanur' as the routine uses 'scanu' to convert values and doesn't set the radix itself. The syntax of the list is almost the same as the list in DEBUG, where in fact I got the idea from. You have from 0+ data items, optionally seperated by commas. Whitespace can be used freely as a delimitor and no delimitors are necessary where there is no need for them (eg: between a value and a string).

The routine takes several parameters, the address of your string (DS:SI), the address of somewhere to store the converted data (ES:DI), the size of the data store (CX) and the size of a unit (AL). The unit size can be byte (AL=1), word (AL=2), dword (AL=4).

Each data item, as in value/string character, is zero-padded to the unit size for storing. Also values are checked that they are in range for the unit size. This method therefore allows us to have those silly word strings.

Here are some examples, all of these assume that we had set the radix = 010h (by calling 'scanur' with AL=010h) :-

Calling with AL=1, and our string=1 2 3 "ABC" yields:-

01 02 03 41 42 43

Calling with AL=4, and our string="0"1FE08 2 yields:-

30 00 00 00 08 FE 01 00 02 00 00 00

Calling with AL=2, and our string=9A06 87"DEF" yields:-

06 9A 87 00 44 00 45 00 46 00

Calling with AL=2, and our string="ABC"FE0FE 0 1 2 yields:-

ERROR! CF=1 (FE0FE>FFFF)

A particularly powerful feature of this routine is that it takes a parameter giving the size of your data store (in bytes). This means that it will be impossible for the program to be crashed because there was too much data. Programmers are generally too lazy to do this sort of range checking, and much to their woe as one particularly wily hacker attack called 'crashing the stack' has taught.

Example; if we called with AL=2, CX=4 and string=1 9 F

ERROR! CF=1 (01 00 09 00 0F 00 > 4bytes)

As an aside, the function is not entirely the same as DEBUG's list scanner. With DEBUG the strings are always converted to byte lists, no matter what the unit size is. It is trivial to modify the routine to work in this way.

One last note is that the end of the list is the first invalid character in the string, this not being an error of course since it is the responsibilty of the controlling parser to decide this based on the context; eg: DEBUG might check for a semicolon comment on the end of the line, though as a matter of fact it doesn't. A premature ending (ie: 0 byte appearing inside the quotes of a string token) will abort with error, thus;

AL=1, string=0A 98"unterminated string yields:-

ERROR! CF=1 (unterminated string)

========START OF CODE======================================================

;
;scalst- data list scan/convert routine ;

;entry:     DS:SI=string
;           ES:DI=store
;           CX=bytes size of store
;           AL=unit size (1=byte,2=word,4=dword)
;           DF=0
;
;           "scanur" must have been called at least once previously
;           in order to set the radix of scanned values
;
;        !! entry parameters are not validated and invalid entry
;        !! parameters will cause undefined behaviour
;
;exit:      CF=1=>error (parse/overflow)
;           CF=0=>okay, then:
;               ZF=1=>no data scanned, ie: CX=0
;               ZF=0=>data scanned
;           SI=updated to the first invalid character
;           DI=updated to the end of converted data + 1
;           CX=bytes converted data (invalid on overflow error)
;
;note:      requires routines "scaws" and "scanu"

;

scalst PROC NEAR

;
;initialise stack frame
;[BP-4] (dw) size mask

;            =000000FFh for unit size 1
;            =0000FFFFh for unit size 2
;            =FFFFFFFFh for unit size 4

;[BP-6] (w) unit size
;[BP-8] (w) original data offset DI
;
;EAX is preserved and the main loop is entered ;

        ENTER 8,0
PUSH EAX
CBW
MOV [BP-6],AX
NEG AL
AND AL,3
SHL AL,3
PUSH CX
XCHG CX,AX
OR EAX,-1
SHR EAX,CL
POP CX
MOV [BP-4],EAX
MOV [BP-8],DI
JMP SHORT inlop

;
;main loop head
; ignore any whitespace and skip the optional comma ;
lop: CALL NEAR PTR scaws

        CMP BYTE PTR [SI],','
JNZ SHORT ko
INC SI

;
;main loop entry
; ignore any whitespace and if a value token is recognised ; write it to data store and continue loop ;
inlop: CALL NEAR PTR scaws

ko:     CALL NEAR PTR scanu
JC SHORT don
JZ SHORT ko2

;
; check that the value is in range for the unit size, if not ; abort here with an error
;

        CMP [BP-4],EAX
JC SHORT don
CALL NEAR PTR wracc
JMP lop

;
; no value was present so check for a string ;
ko2: CMP BYTE PTR [SI],022h

        CLC
JNZ SHORT don

;
; get string into data store
;

        INC SI
XOR EAX,EAX

lop1: MOV AL,[SI]
;
; unterminated string causes an error abort, LODSB is not used for the ;load in order to ensure that [SI] will point to the invalid character ;

        CMP AL,1
JC SHORT don
INC SI
CMP AL,022h
JZ lop
CALL NEAR PTR wracc
JMP lop1

;
; exit point for 'wracc' routine below, clean-up the stack ;
err0: POP EAX

;
; main exit point. the carry flag is preserved as this is used ; for both error and normal exits. the number of bytes stored ; is calculated into CX, the INC/DEC ensuring ZF=1 if this was zero ;
don: LAHF

        MOV CX,DI
SUB CX,[BP-8]
SAHF
INC CX
DEC CX

;
; restore the only corrupted register and 'LEAVE' ;

        POP EAX
LEAVE
RET

;
;wracc- write datum in accumalator to data store ; AL/AX/EAX is written to the data store depending on the unit size. ; throughout the routine DI is the offset into the data store and ; CX is the #bytes left in it. these are updated but if there are ; insufficient bytes remaining in the store we abort with error, taking ; care to clear the 4 bytes (AX + return address) off the stack first ;
wracc: PUSH AX

        MOV AX,[BP-6]
SUB CX,AX
JC err0
CMP AL,2
POP AX
JZ SHORT ko0
JNS SHORT ko1
STOSB
RET

;
; note that 066h STOSW = STOSD
;
ko1: DB 066h
ko0: STOSW

RET

scalst ENDP

========END OF CODE========================================================