ASM Edit 1.82a
(An excellent use of TSR Cracking)

by madmax! / PC97

(13 August 1997, slightly edited by Reverser)


Courtesy of Reverser's page of reverse engineering

Well, I'm happy to host this nice little tutorial by madmax... it's really interesting and well written... btw, it was time to get back to some "muscled" DOS int16 cracking!
ASM Edit 1.82a
An excellent use of TSR Cracking =)
by madmax! / PC97
This essay is about a VERY interesting program I came across. The program is ASM Edit 1.82a and
can be found at: 
http://www.bonn-online.com/~tels/thegurus/bin/aedt182a.zip 
The program is a DOS IDE for writing Assembly, but I heard it also supports Pascal and C. More
importantly, the protection it uses it rather standard, yet unique. Follow me through this
essay, and learn alot. But remember to have fun always! 
You will need the following tools: 

Winice 2/3.x 
Hiew 5.6x 
An open mind! =) 

After installing the program, we run it through the recommended AE.BAT. I broswed the batch
file(as you should always do with batch files) and noticed it just sets some environments(which
actually caused a problem under win95, so i removed them) and runs ASMSHELL.EXE with %1 %2 to
pass command line parameters. It loads up fine without any delays/nags,WOW, friendly shareware
=) So I browse around the program, and begin typing some sample ASM code and suddenly this
window appears,ACK. Its an annoying shareware reminder! So from what we know(or learned from
+ORC or others), lets start the proccess. Were stuck at a window waiting for keyboard input, so
lets try 'BPINT 16'. Hmm..doesnt catch, so lets try 'BPINT 10'. We choose the ACCEPT button,
and the box is gone, with no BREAK! Is it possible the program doesnt use interrupts? Lets exit
and browse the ASMSHELL.EXE with Hiew. It looks like a standard DOS executable, so lets see
what else we've got in the program directory: 

AEO18_A  ICO     <=== ??? AEO18_B ICO <="==" Not sure, there not window$ icons ASMEDIT EXE <="==" Main Program EXE? ASMEDIT HLP "" ASMSHELL EXE <="==" The loader called in AE.BAT DESCRIPT ION DPMI16BI OVL <="==" Dos Protected Mode Integration 16-Bit File EXTERNAL BAT NEWCOM ASM NEWEXE ASM RTM EXE <="==" Borland Loader for DPMI Lets look at ASMEDIT.EXE, immediately we notice in the first 3000 bytes a bunch of Protected Mode text. Ahh, so thats why our BPINT's didnt work. For some reason, Winice doesnt seem to break on Interrupts sometimes under PMODE. Ive cracked numerous games and have traced a file open down to INT21/AH="3D," yet that same BPINT wont break(perhaps a certain Winice GURU will figure it out and lemme know=")." So lets return to our Nag, select File/New and type in a couple letters, go conjure up a good martini(or a cold beer if your American=")" and when you return, our Nag is back. While BPINT may not break, we know its using interrupts, so lets take a bit more direct approach. Lets set a bpx on the first instruction of the INT 16 handler. To find it we do this in Winice: :? 16*4 /* (Each INT has 4 bytes, the first 2 being the IP, last 2 CS) */ 00000058 0000000088 "X" So now we know that 0:58 is the pointer to INT 16, lets display it. :d 0:58 (if you get an 'Invalid Selector' error, keep popping in and out of Winice til you end up in a DOS routine or service) Now you should see the Pointer at the upper-right corner of your data window. For me it listed like this: 0000:00000058 2D 04 70 00 28 0A 58 02............ The first 4 bytes are all were interested in, so lets take a look at the routine's code: :u 0070:042D You SHOULD see the disassembly of the INT 16 handler, mine started with a STI,PUSHF. So now lets but a bpx on the first instruction. :bpx 0070:042D Now, lets leave Winice(F5 for me). BAM, an immediate break! Now just step over the instructions, you should hit a RETF, then an ARPL, and your back in the programs code, heres a snippet: mov ah,001 int 016 mov ax,00000 mov bx,ax je 0000B023D mov ah,000 int 016 xchg bx,ax And to our amazement, its using INT 16!=")" Trace like crazy til you come across this section of code: les di,[bp+6] inc word ptr es:[di+9D] <="===" Important=")" mov ax,es:[di+9D] and ax,003FF or ax,ax je 00001576B jmp 0000158DF Well..Put a 'BPX' on that instruction and watch what happens. Its being incremented very fast. Probably with each click of the timer interrupt. So lets try putting this *counter* to a halt. Lets apply the following patch: Change 26 FF 85 9D 00="==">   EB 01 EA 48 40 

Strange you may ask? Heres the result: 

0015757   jmp  1575A 
0015759   jmp  8B26:04048 
See what happens? The code jumps into itself, its called byte shifting. I use it as often as I
can to avoid curious authors from using the dead list approach. It does the same thing as 5
Nops would do too. Lets apply the patch and run it. An error in REALITY.SYS appears, its a
little joke from the author cause we failed the CRC Check. Lets track it down using 
'BPINT 21 if ah==3d'. The first 10 breaks or so will be COMMAND.COM messing with the batch
file, then it will break inside ASMSHELL.EXE and do a 
'D DS:DX' and you will see its opening ASMEDIT.EXE. Do a 'P RET' and then go about 4 pages down
in the code, and youll see the following: 

mov   al,[0876]                <=== Perhaps the CRC result? mov [0006],al <="==" Save it to this mem location cmp byte ptr [0006],00 <="==" Is it 0? jz 0EF6 <="==" If so, go on Good Guy! call 03F8 <="==" If not, then REALITY slaps us So lets work around this part in the following way: mov al,[0876] mov [0006],al mov byte ptr [0006],00 <="==" Theres the patch=")" jmp 0EF6 <="==" We go on, leaving reality behind=")" Note: Changing the Jz="=="> JMP will not suffice, as there is a check later on in the program,
the flag must be set! 

Ok, lets search for the routine in ASMSHELL.EXE, its   A0 76 08 A2 06 00 
Hmm..No match! Well, ill save you the work and let you know that this file is very well
encrypted and I dont feel like doing it the hard way. So lets do a TSR CRACK! First step is to
find an entry point, lets use INT 21/AH=3D 
This program also has a 30-day which we will kill too with the TSR, so the rest of this essay
will be finished through the source: 

;Start of AE-T.ASM 

Code    Segment Byte Public 
Assume  Cs:Code, Ds:Code 
Org     100h 

Start: 
   mov  dx,Offset Welcome               ; Greets, ETC =) 
   call Print 

; We will first patch the file to fix the Counter... 

   mov  ax,3D02h                        ; Open file for Read/Write 
   mov  dx,offset Fname                 ; Pointer to FileName 
   int  21h 
   jnc  fileok                          ; If it opens ok, go on 
   mov  dx,offset Nofile                ; If not, print error msg 
   call Print 
   int  20h                             ; And Exit 

fileok: 
   mov  bx,4202h                        ; Seek to EOF 
   xchg ax,bx                           ; Exchange file handle to bl 
   xor  cx,cx 
   xor  dx,dx 
   int  21h 
   cmp  dx,Offset FsizeHigh             ; Is high word of filesize equal? 
   jnz  error                           ; If not, then abort 
   cmp  ax,Offset FsizeLow              ; Is low word of filesize equal? 
   jnz  error                           ; If not, then abort 
   mov  ax,4200h                        ; Move pointer from start of file 
   mov  cx,Offset HighPatch             ; High word to move 
   mov  dx,Offset LowPatch              ; Low word to move 
   int  21h 
   mov  ah,40h                          ; Write to file function 
   mov  cx,5                            ; Number of bytes to patch 
   mov  dx,Offset Patchdata             ; Pointer to patchdata 
   int  21h 
   mov  ah,3Eh                          ; Close file function 
   int  21h 
   jmp  done                            ; Goto TSR Start 

error: 
   mov  dx,offset ErrMsg                ; Print error msg 
   call Print 
   int  20h                             ; Exit 

done: 
   mov  dx,offset Patchok               ; Print patchok msg 
   call Print 
   mov  ax,3521h                        ; Get INT21 vector 
   int  21h 
   mov  word ptr JmpNfo+1,bx            ; place IP of it in JMP 
   mov  word ptr JmpNfo+3,es            ; place CS of it in JMP 
   mov  ax,2521h                        ; set new INT 21 
   mov  dx,offset tsrcode               ; pointer to new INT 21 
   int  21h 
   mov  dx,offset IntHooked             ; print success msg 
   call Print 
   mov  cx,1E41h                        ; these following lines 
   call KbdBuff                         ; fill the keyboard buffer 
   mov  cx,1245h                        ; with AE.BAT and a CR/LF 
   call KbdBuff 
   mov  cx,342Eh 
   call KbdBuff 
   mov  cx,3042h 
   call KbdBuff 
   mov  cx,1E41h 
   call KbdBuff 
   mov  cx,1454h 
   call KbdBuff 
   mov  cx,1C0Dh 
   call KbdBuff 
   mov  ah,31h                          ; TSR Function 
   mov  dx,40h                          ; reserve 40 paragraphs of mem 
   int  21h 

KbdBuff Proc 
   mov  ah,5 
   int  16h 
   ret 
KbdBuff EndP 

Print Proc 
   mov  ah,9 
   int  21h 
   ret 
Print EndP 

; HERES THE START OF THE NEW INT21 
tsrcode: 
   cmp  ah,2Ah                          ; Is the INT21 call for the date? 
   jnz  term                            ; if not, test for other function 
   mov  cx,7CDh                         ; if so, then set year to 1997 
   mov  dx,80Bh                         ; and date to August 11 
   iret                               &nb! sp; ; and IRET to program 

; I used August 11 cause I installed on the 10th, adjust for your needs 
term: 
   cmp  ah,4Ch                          ; is it a terminate? 
   jnz  checksum                        ; if not, perhaps its a file open 
   push es                              ; save ES 
   push ax                              ; save AX 
   xor  di,di 
   mov  es,di                           ; set ES to 0 
   mov  di,84h                          ; 4 * 21h == 84h 
   mov  ax,word ptr cs:[JmpNfo+1]       ; place IP of original INT21 in bx 
   stosw                                ; store AX at ES:DI and add 2 to DI 
   mov  ax,word ptr cs:[JmpNfo+3]       ; place CS of original INT21 in bx 
   stosw                                ; store AX at ES:DI 
   pop  ax                              ; restore ax 
   pop  es                              ; restore es 
   jmp  bye                             ; jump to INT21 

checksum: 
   cmp  ah,3Dh                          ; is it a file open function? 
   jnz  bye                             ; if not, goto INT21 
   push es                              ; save ES 
   push di                              ; save DI 
   add  sp,0Eh                          ; adjust SP to a couple CALLS back 
   pop  di                              ; pop the IP of the call to di 
   add  di,6Ch                          ; adjust DI to the proper point 
   pop  es                              ; pop the correct segment 
   cmp  word ptr es:[di],3474h          ; is it the CRC checksum(the jz)? 
   jnz  notright                        ; if not, skip patching memory 
   mov  byte ptr es:[di],0EBh           ;  patch the JZ ===> JMP 
   mov  word ptr es:[di-5],06C6h        ; changes CMP ===> MOV 

notright: 
   sub  sp,12h                         ; re-adjust SP 
   pop  di                             ; restore original DI 
   pop  es                             ; restore original ES 

bye: 
JmpNfo    DB  0EAh,0,0,0,0 
Welcome   DB  13,10,'ASM Edit 1.82a TSR Crack by madmax! / PC97',13,10,24h 
FName     DB  'ASMEDIT.EXE',0 
RunPrg    DB  'AE.BAT',0 
IntHooked DB  'Interrupt Successfully Hooked.',13,10,24h 
NoFile    DB  13,10,'ASMEDIT.EXE not found, be sure your in the right directory!',13,10,24h 
ErrMsg    DB  13,10,'Error while patching ASMEDIT.EXE!',13,10,24h 
PatchOK   DB  'ASMEDIT.EXE Patched.',13,10,24h 
FSizeHigh EQU 0006h 
FSizeLow  EQU 4027h 
HighPatch EQU 0000h 
LowPatch  EQU 6757h 
PatchData DB  0EBh,01h,0EAh,48h,40h,0 

Code Ends 
End Start 

; End of AE-T.ASM 

Well, I hope you have learned from this essay! I think its an excellent example of an author
who encrypted his code well, but yet we still find a way of *fixing* the software! This TSR is
great, it handles the Date check by taking over INT21/AH=2A, and when it detects the CRC check,
it patches the program in memory. The INT21/AH=4C check is simply to restore the original INT21
upon the termination of the program. Good luck with it! 

-- madmax! -- Remember to have fun! 
   
(c) madmax! 1997. All rights reserved
You are deep inside reverser's page of reverse engineering, choose your way out:

homepage links red anonymity +ORC students' essays Academy database
tools cocktails antismut CGI-scripts search_forms mail_Reverser
Is reverse engineering illegal?