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... It really doesn't matter what language a program was

written in in order to crack it, because all programs do the same

thing. And that is issue commands to the microprocessor. And all

programs when broken down to their simplest form are nothing more than

a collection of 80XXX instructions and program specific data. This is

the level of assembly language. In 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 ripped the ED!SON

introduction. Yes, i've taken it ;) Why should i do something if

someone already did ? So for all of you that didn't have the chance to

have that intro, i've a little remixed it, and here 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 (http://www.numega.com). 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 select. When

selected, the part of the config file refering to it is runned and

followed by the [common] one. In the autoexec.bat there's a %config%

variable set to the user'selection and is used to select witch part of

your bat you will execute.

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 "WR" En/Disable, "R", "Alt-R" Edit.

FPU Registers

Window "WF" En/Disable.

Locals Windows "WL" En/Disable, "Alt-L" Focus.

Watch Window "WW" En/Disable, "Alt-W" Focus.

Data Window "WD" En/Disable, "E", "Alt-D" to Edit.

Code Window "WC" En/Disable, "A" Edit, "Alt-C" Focus.

Command Window Type Commands and read output here.

Help Line 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 numbers with the colon in the middle of them to the

far left of the window is the address:offset of that line of code.

Each line of code in this window is an instruction that the program

will issue to the microprocessor, and the parameters for that

instruction. The registers that contain the address for the current

instruction waiting to be executed are the CS: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 ; Disable lowercase

assembly

MOUSE=ON ; Enable mouse

NOLEDS=OFF ; Disable led

switching

NOPAGE=OFF

PENTIUM=ON ; Pentium Op-Codes

THREADP=ON ; Following Thread

Process

VERBOSE=ON

PHYSMB=16 ; Exact Memory Size

SYM=256 ; Memoy allocated 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;" ; Run (CTRL-D)

F8="^T;" ; Step into functions

(Trace)

F10="^P;" ; Step Over functions

(Procedure)

F11="^G @SS:ESP;" ; Step out of function

; Export Symbols

EXP=c:\win96\system\kernel32.dll

EXP=c:\win96\system\user32.dll

EXP=c:\win96\system\gdi32.dll

;--- 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 GetWindowText

:bpx GetWindowTexta

:bpx GetWindowTextw

:bpx GetDlgItemText

:bpx GetDlgItemTexta

:bpx 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 ; BPs list

00) BPX USER!GetWindowText

01) BPX USER32!GetWindowTexta

02) BPX USER32!CharNextExW

03) BPX USER!GetDlgItemText

04) BPX USER32!GetDlgItemTextA

05) BPX USER32!AppendMenuW

:bc 0 1 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 ; Max String Size

0040369D 50 PUSH EAX ; Buffer Address

0040369E 6882000000 PUSH 00000082 ; Control ID

004036A3 56 PUSH ESI ; Dialog Handle

004036A4 FFD7 CALL EDI ; Call GetDlgItemTextA

; Registration Checking

>004036A6 8D442438 LEA EAX, [ESP + 38] ; Registration Buffer

004036AA 8D4C2418 LEA ECX, [ESP + 18] ; Name Buffer

004036AE 50 PUSH EAX ; Save Datas

004036AF 51 PUSH ECX

!004036B0 E80BF9FFFF CALL 00402FC0 ; Registration Check

004036B5 83C408 ADD ESP, 00000008 ; Free Stack

004036B8 85C0 TEST EAX, EAX

004036BA 7E6E JLE 0040372A ; EAX=0 Means Bad Reg...

; Do Something, sure... ;)

004036BC 8D442438 LEA EAX, [ESP + 38]

004036C0 8D4C2418 LEA ECX, [ESP + 18]

004036C4 50 PUSH EAX

004036C5 51 PUSH ECX

004036C6 E895FAFFFF CALL 00403160

004036CB 83C408 ADD ESP, 00000008

004036CE 833D44F0480000 CMP DWORD PTR [0048F044], 00000000

004036D5 740B JE 004036E2

004036D7 A144F04800 MOV EAX, [0048F044]

004036DC 8BC8 MOV ECX, EAX

004036DE 8B18 MOV EBX, [EAX]

004036E0 FF13 CALL DWORD PTR [EBX]

004036E2 833D40F0480000 CMP DWORD PTR [0048F040], 00000000

004036E9 740C JE 004036F7

004036EB A140F04800 MOV EAX, [0048F040]

004036F0 8BC8 MOV ECX, EAX

004036F2 8B18 MOV EBX, [EAX]

004036F4 FF5314 CALL [EBX+14]

; Close Registration Windows, And pops : "Thanks Registering"

004036F7 6A01 PUSH 00000001

004036F9 56 PUSH ESI

004036FA FF15F4DA4900 CALL [USER32!EndDialog]

00403700 6A00 PUSH 00000000

00403702 6820324000 PUSH 00403220

00403707 56 PUSH ESI

00403708 FF15F8DA4900 CALL [USER32!GetParent]

0040370E 50 PUSH EAX

0040370F 68E4000000 PUSH 000000E4

00403714 A148F04800 MOV EAX, [0048F048]

00403719 50 PUSH EAX

0040371A FF1544DB4900 CALL [USER32!DialogBoxParamA]

00403720 B801000000 MOV EAX, 00000001

00403725 E92EFFFFFF JMP 00403658

; Pops up a window saying : "Your name and registration code do not match."

0040372A 6A00 PUSH 00000000

0040372C A104F34800 MOV EAX, [0048F304]

00403731 50 PUSH EAX

00403732 68ACF34800 PUSH 0048F3AC

00403737 56 PUSH ESI

00403738 FF15E4DA4900 CALL [USER32!MessageBoxA]

0040373E 6882000000 PUSH 00000082

00403743 56 PUSH ESI

00403744 FF15F0DA4900 CALL [USER32!GetDlgItem]

0040374A 50 PUSH EAX

0040374B FF1548DB4900 CALL [USER32!SetFocus]

00403751 B801000000 MOV EAX, 00000001

00403756 E9FDFEFFFF 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 "CTRL-PGDOWN".

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 PUSH ESI

00402FC1 8B742408 MOV ESI, [ESP + 08]

00402FC5 56 PUSH ESI

00402FC6 E835000000 CALL 00403000 ; check name length (1st)

00402FCB 83C404 ADD ESP, 00000004

!00402FCE 85C0 TEST EAX, EAX

!00402FD0 7504 JNE 00402FD6 ; branch is followed

!00402FD2 33C0 XOR EAX, EAX ; Set EAX to 0 (BAD!)

00402FD4 5E POP ESI

00402FD5 C3 RET ; Exit 1

; Check Registration Code

:00402FD6 8B44240C MOV EAX, [ESP + 0C]

:00402FDA 50 PUSH EAX

:00402FDB 56 PUSH ESI

:00402FDC 6848F34800 PUSH 0048F348 ; "-294378973"

:00402FE1 E86AE70100 CALL 00421750 ; The key is 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 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 ax,cs

mov ds,ax

mov es,ax

mov ax,3d02h

mov dx,offset cs:fname ; DX=*FileName

int 21h ; DOS/FileOpen

jc errorlbl ; Jump On Errors

mov word ptr [offset cs:fname],ax ; BX=Handle

mov bx,ax

mov ax,4200h

xor cx,cx ; Segment

mov dx,23ceh ; Offset

int 21h ; DOS/FileSeekSet

jc errorlbl ; Error !

mov ax,4000h

mov bx,word ptr [offset fname] ; BX=Handle

mov cx,6 ; Lenght

mov dx,offset patch ; Buffer

int 21h ; DOS/WriteFile

jc errorlbl

mov ax,3e00h

mov bx,word ptr [offset fname] ; BX=Handle

int 21h ; DOS/CloseFile

jc errorlbl

mov dx,offset cs:text2

jmp getout

errorlbl:

mov dx,offset cs:text1 ; Print

getout: mov ah,9

int 21h

mov ah,4ch ; Get Out Of Here !

int 21h

patch db 0B8H,001H,000H,000H,000H,090H ; MOV EAX,00000001 - NOP

fname db 'ACDSEE32.EXE',0

text1 db 0ah,0dh,'Error Handling File'

text2 db 0ah,0dh,'Patch By Exact /oRP',0ah,0dh,'$'

end;--- 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