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

by madmax! / PC97

(13 August 1997, slightly edited by Fravia)


Courtesy of Fravia'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 fravia'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_Fravia
Is reverse engineering illegal?