An addition on a "Ready Made Protection":
Sales Agent

Written by Christal
With the Help of Neutral AtomX and Psyché

A few big firms have adopted this Ready Made Protection, and i'm sure that you have already seen it. For this essay, I've used 8 different programs, with not the same option selected by the editor, and I will try to fly around this protection

Soft Ice

Macromedia DreamWaever 2.0
  Director 7
  FireWorks 2
  Flash 3.0
  Flash 4.0
Adobe Image Ready 1.0 (French Version)
  Image Styler 1.0
Symantec Norton Utilities (courtesy of Goth)


It seems there has been 3 versions of this protection, according to Goth, although Release SoftWare Corps, on its site, only tells about a version 2.0
The protection allows giving applications during Trial Periods on a limited amount of time. At the end of the testing period, the sending of the application was not possible, with an on-line buying opportunity to unlock the shareware.
All that can be parameterized by the society who want to deliver his products as "Try before you Buy".
The protection is made by converting the first hand execute as a file having dl_ as extension and with will be discompressed during the user's recording.
These essay has been realize by studying 8 programs protected by this ready made protection, and i think that all the different cases of been seen.


Following the protected programs you will meet, you will have all part of these cases:

  • Setting up of a locking key at the end of the testing time
  • Setting up of a locking key ins case of clock movement (fwd/bwd)
  • It seems that an other locking key is set up if the checksum of the protection has detected a change in its files. This key stays operating, even when replacing a no changed executable in the application directory.
  • Recording options (Buy Now) be serial entrance, if the option is configured.
  • Discompression of a dl_ file in case of recording and transforming the shareware in a full version.

1- The Time Limit key

(Contribution of Neutral AtomX)

To know how this key can be set up, i've put up Filemon and Regmon with the capture of all events (as an option). Then i've installed the product. At the end of the installation, i've saved all this informations collected by Filemon and Regmon (they are quite a lot!).

Consulting the files generated by Filemon and Regmon:

Up to consult easily this great of lot informations, i've imported the generated text files into an Excel page, added a line with column's heads and used the option "data/filter/automatic filter".

You obtain then z mini database with lists allowing choosing the information searching parameters. For instance: show on screen all the "Set valueEx" events that occurred in the register basis by all processes or by one given process, or show all the events generated by the exe. Process...

Each time the information are saved on an Excel page, which allows later on to compare the events according to the different steps (install, setup, time expired). A first examination of these informations can lead to a general idea of "Who does what and where".

Capture of events when an executable file is launched

Same way: you start up Regmon and Filemon, then you open the target for the first time. When you get the Shareware screen (30 days left), you save the informations you've got to import then into Excel. You click on "Cancel" not to fire the application.

An examination of the "setValueEx" helps to detect some key (suspected) accesses [HKEY_CLASSES ] with 3 entrances ("xlate", "write", "open"), already seen in the first step.

A first care with the help of REGEDIT.EXE is to put oneself on the key and to save it under the following name: utlxfiles_J+0.reg (J+0 is the installing day). You can then restore this key is necessary.

Changing of the system date: Move the clock forward (J+0 to J+1), and restart Filemon , Regmon and the target. The screen shows "29 days left". As before, save the collected informations. An examination of these events indicates the same accesses to the register Basis.

Save the key [HKEY_CLASS] under the following name: utlxfile_J+1.reg, and with the help of HexWork32.exe, compare the content of these two files, you will see (as previous) that only some bytes have been changed (in the "write= hex:..." entrance)

Capture of events at the end of the Time limit (J+31)

Changing of the system date: move clock 31 days forward (J+0 to J+31)

Still the same, prepare the capture of the events, then start up the application which, this time, indicates that the time limit is over, and you have no more choice than to leave.

Exanimate in Excel the imported Data and find the new access:

Filemon: write on the file c:\330XXXXX.sys

And an access to the file C:\Windows\System\RSAPIERR.txt, which is still empty

Uninstall of the Target

All right, the lock-key is putting on by sales Agent!

After having completely uninstall the target, we look what is append to our 3 suspects...

BINGO ! There are always in place !

  • C:\3l6fao30.sys
  • C:\windows\system\RSAPIERR.txt
  • [HKEY_CLASSES_ROOT\ultxfile\Format\MSHA0J0V]

If you want to be able to make a clean re-installation, you need to replace these 3 files. 

Time-limit Sales Agent : For playing in total security

If you want to play with your clock in every direction to look at the reaction of the protection, here is what you do make, if you don't want to have surprises:

  • Before the first launch of the application, save the key [HKEY_CLASSES_ROOT\ultxfile\Format\MSHA0J0V]. By clicking on the " utlxfile_J+0.reg " you can restore the (J+0)situation.
  • Erase the C:\3l6fao30.sys file, just after the expiration date. It will be automatically restored by Sales Agent at the next launch (with the correct parameters)
  • Erase the C:\windows\system\RSAPIERR.txt file, if this one have been modified (it's append when the date of the system clock is backward at the setup date). Generally, your are informed by a messagebox " Resources Security Altered : the System clock have been set etc.. "

How does Sales Agent use all that ?

The expiration date is saved in the HKEY_ .. Format\MSHA0J0V key

At each time you fire the target, it checks if the current date is over the setup date and over the date of the last use of the program. If all is right, it replaces the date of the last launch by the current date.

It explain why we can move forward the clock (i.e. : J+10) to see how many days you can use the target, but you cannot go backward (i.e. : J+9).

In that case, the Try Button cannot be acceded, and an error is writing in the file: C:\windows\system\RSAPIERR.txt .

Here is an example of what you can find in this file:

" func - tSystemValidityCheck() , system time - 936738923 saved time - 939503697

tUpdate() status -> RS_APP_STATUS_TAMPERED event -> RS_EVENT_SYS_T_INVALID subreason -> tSystemValidityCheck() "

When the expiration date is over, the file C:\3l6fao30.sys is modified definitively

2- Checksum and Controls

Just some version of this protection used a checksum

If you modify something, the checksum will activate a message box "Important application files are missing or corrupted ...". By putting a breakpoint on MessageBoxA you can found the next lines:

 * Possible StringData Ref from Data Obj ->"^^L;dIZ8"
 :0040AB68 6894CB4300              push 0043CB94
 :0040AB6D 6830B44400              push 0044B430
 :0040AB72 E8C95F0100              call 00420B40
 :0040AB77 83C408                  add esp, 00000008
 :0040AB7A 6A00                    push 00000000
 :0040AB7C 6A00                    push 00000000
 :0040AB7E E86D980000              call 004143F0
 :0040AB83 83C408                  add esp, 00000008
 :0040AB86 83F801                  cmp eax, 00000001
 :0040AB89 7458                    je 0040ABE3		> no jump
 :0040AB8B 6869010000              push 00000169
 :0040AB90 E8BB9B0000              call 00414750
 :0040AB95 83C404                  add esp, 00000004
 :0040AB98 6810200000              push 00002010
 :0040AB9D 6A00                    push 00000000
 :0040AB9F 68A4584500              push 004558A4
 :0040ABA4 6A00                    push 00000000
 * Reference To: USER32.MessageBoxA, Ord:01BEh
 :0040ABA6 FF1598224300            Call dword ptr [00432298]

If you inverse the Zero Flag when you will be at 0040AB89, you can bypassed this first control. A second control will be made and an other time the message "important application files..." will popup.

 :0040ABE3 E8C1FDFFFF              call 0040A9A9
 :0040ABE8 E833A2FFFF              call 00404E20
 :0040ABED 85C0                    test eax, eax
 :0040ABEF 7537                    jne 0040AC28		> no jump
 :0040ABF1 6869010000              push 00000169
 :0040ABF6 E8559B0000              call 00414750
 :0040ABFB 83C404                  add esp, 00000004
 :0040ABFE 6810200000              push 00002010
 :0040AC03 6A00                    push 00000000
 :0040AC05 68A4584500              push 004558A4
 :0040AC0A 6A00                    push 00000000
 :0040AC0C FF1598224300            Call [USER32.MessageBoxA]

By inverting the Zero Flag in 0040ABED, you will have a first "Break due to general protection fault":

After having replaced a clean copy of the target, the program would bypass these 2 controls without problem (jump), and the Loader of the application will check the C:\windows\system\RSAXXXX.txt's file. Function of the result, it will popup a DialogBoxParamA "Due To Security problems, your free trials...", If you have move on/move back your system date:

 0137:004149ED  FF15D4224300        CALL    [USER32!DialogBoxParamA]
 0137:004149F3  A1ECFF4400          MOV     EAX,[0044FFEC]
 0137:004149F8  85C0                TEST    EAX,EAX
 0137:004149FA  7443                JZ      00414A3F
 0137:004149FC  A110004500          MOV     EAX,[00450010]
 0137:00414A01  50                  PUSH    EAX

And the shareware screen will appeared with 2 buttons, Try and Cancel, the first one grayed if the lock key have been set. 

3- The different Options

How can we resolve the situation?

A first approach, but not very elegant, is to replace all the 30 days, the " utlxfile_J+0.reg ".key, in the Register Base.

A second method, if the option have been selected at the origin, is to play with the register Box.:

The registration Box

On the Shareware screen, you could have a "Buy Now" button. By selecting this button, you could be able to register: 

This registration could be made in 2 times:

  • a first registration box, actived by the ready made protection
  • a second one, actived by the original target 

RSAGNT32.Dll (525 ko) : Dead Listing

when launching the application, the Setup will propose you to try, or buy, the proggy. If you click on "Buy Now", several screen will be offer to you: one for your identification (Name, Forename, Company), an other for Credit Card information's. If you don't like that, you can put a MessageBoxA's breakpoint in SoftIce and click on the "Next" button. Without the information's waited, the message box will popup. Before is apparition, SoftIce will Break. Make F12 to go back in Rsagnt32, and put a bpx on the conditional jump (jz) some lines up. At the next time, an R FL Z entered on the command line of the debugger will permitted you to continue with empty fields.

After a disassemble of this DLL in W32dasm, the " String Data References " would give you a certain number of information's, like:

- SalesAgent Demo
- This is a demo. Unlocking
- Sorry, that unlocking code is not valid for this program
- Invalid Unlocking Code

  • You can notice that this information's could be found in the different Rsagnt, with or without the option Buy Now parameted.

By your don't have any string like " Thank You... "
In this listing (a bit longer) you could see a typical example of a protection where all the informations are in the same corner. That is in these lines where you can found the solution...

* Referenced by a CALL at Address:
:100055A0 A170160310              mov eax, dword ptr [10031670]
:100055A5 81EC70020000            sub esp, 00000270
:100055AB 85C0                    test eax, eax
:100055AD 53                      push ebx
:100055AE 55                      push ebp
:100055AF 56                      push esi
:100055B0 57                      push edi
:100055B1 7533                    jne 100055E6  -> go to the registration information's
:100055B3 8B842484020000          mov eax, dword ptr [esp+00000284]
:100055BA 6A40                    push 00000040

* Possible StringData Ref from Data Obj ->"SalesAgent Demo"
* Possible StringData Ref from Data Obj ->"This is a demo. Unlocking"
* Reference To: USER32.MessageBoxA, Ord:0195h
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
* Reference To: USER32.GetDlgItemTextA, Ord:00F5h -> get the registration information's
* Possible Reference to Dialog: DialogID_07DB, CONTROL_ID:0416, ""
* Possible StringData Ref from Data Obj ->"Sorry, that unlocking code is "
                                        ->"not valid for this program."

If you search in the different Calls called between the addresses 100055ED and 1000561A, you probably have the chance to found the echo of the Unlock Reg. key, but there are simpler.
This subroutine is called by the offset 1000543B. A conditional jump could bypassed this call, and it's logical if your are a registered user...
* Referenced by a (U)nconditional or (C)onditional Jump at Address:

:10005436 8B742448                mov esi, dword ptr [esp+48]
:1000543A 56                      push esi
:1000543B E860010000              call 100055A0 --> bad Guy

And it seem that a jump like that exist!

:100053C7 48                      dec eax
:100053C8 746C                    je 10005436 -> here
:100053CA 48                      dec eax
:100053CB 7443                    je 10005410
:100053CD 2D44040000              sub eax, 00000444
:100053D2 0F850D010000            jne 100054E5
:100053D8 8B742448                mov esi, dword ptr [esp+48]
:100053DC 6A44                    push 00000044

Possible StringData Ref from Data Obj ->"Re-register"

To verify this theory, you can check with SoftIce by putting a breakpoint in 100053C8 and an other in 100055B1. At each break, an inversion of the state of the zero-flag (R FL Z) is enough.
The first step is finish, without the need of a hexeditor.

Target.exe : Live approach

Now, it's the application which has the hand. Sales Agent is Out !

You will discover a second registration box: Name, Forename, Company, and a serial number, which must begin by FLW300-
It that case, the target dispose of his own protection against the disassemble. So, no resources, no String Data references, no code. Just the Strings DialogBox, the exported and imported modules and a "Entry Point" of the program beginning at 00494150, in place of the usual 00401000
After filing the Reg. Box, and put a Bpx GetWindowtextA., at the break, make F12 tout go back to the target. You will be at 004B9490.
When tracing with F10 in SoftIce, you will go back 5 times at this offset before seeing the box " This product cannot run without your name and serial number… " at 00541639.

0177:00541608  51                  PUSH      ECX
0177:00541609  E8F2FAFFFF          CALL      00541100
0177:0054160E  83C404              ADD       ESP,04
0177:00541611  8945E8              MOV       [EBP-18],EAX
0177:00541614  85C0                TEST      EAX,EAX
0177:00541616  7531                JNZ       00541649 
0177:00541618  8D4DF0              LEA       ECX,[EBP-10]
0177:0054161B  E8E5C4F6FF          CALL      004ADB05
0177:00541620  687F020000          PUSH      0000027F
0177:00541625  8D4DF0              LEA       ECX,[EBP-10]
0177:00541628  C645FC03            MOV       BYTE PTR [EBP-04],03
0177:0054162C  E876E0F6FF          CALL      004AF6A7
0177:00541631  6A00                PUSH      00
0177:00541633  8B45F0              MOV       EAX,[EBP-10]
0177:00541636  6A30                PUSH      30
0177:00541638  50                  PUSH      EAX
0177:00541639  E8A07AF7FF          CALL      004B90DE  -> " invalid code "

Some line forward, the jnz 00541649 could jump over this nasty call. This jump depend of a test eax, eax. In most of the case, it is in the call, which is before, than the value of this register is set.
Get putting a Bpx 00541609, and go out SoftIce (F5)
At the next validation of the Reg. Box, made a " d ecx " and look at the content of this register, before beginning the reward of the manipulations made on EAX in the call we have seen.

It's not the good serial here, but our. The call 00541100 is probably the one which control his validity.

You will land in a small procedure with a call 0045A520

0177:0045A520  83EC20              SUB       ESP,20
0177:0045A523  8D442410            LEA       EAX,[ESP+10]
0177:0045A527  53                  PUSH      EBX
0177:0045A528  8D4C2420            LEA       ECX,[ESP+20]
0177:0045A52C  56                  PUSH      ESI
0177:0045A52D  57                  PUSH      EDI
0177:0045A52E  33F6                XOR       ESI,ESI
0177:0045A530  8D542420            LEA       EDX,[ESP+20]
0177:0045A534  50                  PUSH      EAX
0177:0045A535  8D442428            LEA       EAX,[ESP+28]
0177:0045A539  51                  PUSH      ECX
0177:0045A53A  8D4C2414            LEA       ECX,[ESP+14]
0177:0045A53E  52                  PUSH      EDX
0177:0045A53F  8B54243C            MOV       EDX,[ESP+3C]
0177:0045A543  50                  PUSH      EAX
0177:0045A544  89742424            MOV       [ESP+24],ESI
0177:0045A548  51                  PUSH      ECX
0177:0045A549  8974242C            MOV       [ESP+2C],ESI
0177:0045A54D  52                  PUSH      EDX
0177:0045A54E  E8CD000000          CALL      0045A620
0177:0045A553  83C418              ADD       ESP,18
0177:0045A556  85C0                TEST      EAX,EAX
0177:0045A558  0F84B3000000        JZ        0045A611

When tracing a little (F10), the JZ 0045A611 will land you here:

0177:0045A608  3BF8                CMP       EDI,EAX
0177:0045A60A  7505                JNZ       0045A611
0177:0045A60C  BE01000000          MOV       ESI,00000001
0177:0045A611  8BC6                MOV       EAX,ESI -> here
0177:0045A613  5F                  POP       EDI
0177:0045A614  5E                  POP       ESI
0177:0045A615  5B                  POP       EBX
0177:0045A616  83C420              ADD       ESP,20
0177:0045A619  C3                  RET

At the end of the procedure, EAX will be equal to 0
If your are not patient, you can stop now with this crack, and replace the JZ 0045A611 (0F84B3000000), by JZ 0045A60C (0F84AE000000). In this way, you force EAX = 1, the next jump in 00541616 will be good for you, and you started the discompression of the full version.

But I like to understand
and with some luck, I could found the good serial...

On the same way as before, I'll look into the CALL 0045A620, searching any manipulations on EAX

0177:0045A871  39442414            CMP       [ESP+14],EAX
0177:0045A875  7409                JZ        0045A880  (NO JUMP)
0177:0045A877  33C0                XOR       EAX,EAX
0177:0045A879  5F                  POP       EDI
0177:0045A87A  5E                  POP       ESI
0177:0045A87B  5B                  POP       EBX
0177:0045A87C  83C43C              ADD       ESP,3C
0177:0045A87F  C3                  RET

In 0045A875, the (NO JUMP) push 0 in EAX. Not interesting!
And what can happen if this jump is inverse ?
Well, by tracing a little you land here:

0177:0045A8D0  B801000000          MOV       EAX,00000001
0177:0045A8D5  5F                  POP       EDI
0177:0045A8D6  5E                  POP       ESI
0177:0045A8D7  5B                  POP       EBX
0177:0045A8D8  83C43C              ADD       ESP,3C
0177:0045A8DB  C3                  RET

Very Good ! This one agrees me. One byte to modify, it's exactly what I need, while now we need to found how to modify the exe of the target! To be sure, I've launched my hexeditor, and search the string 740933C05F5E (for the JZ 0045A880 I want to change in JNZ). And I've found it! Modify it without problem, saved the new exe, and at the next launch of the application : all GOOD !

I've been rather surprising: men who disable the possibility of using a disassembler, couldn't imagine that we couldn't use a debugger ?
No encryption, no compression, no little checksum, in this version of this ready-made protection?

Oh! I forgot something, the good serial is FLW300-01567-53532-72983
But it's a other history...
By the way, for one of these targets, the use a tool like a Strings Search has given:

Selected Browser
Receive Error: %d.

Reactivation of a disabled option

For the next 2 targets i've studied, the Reg. Box option has not been selected by the authors of the programs.

Here are the Strings Data references i've seen in first:

Application n°1 Application n°2
00405FF3          expired
00406B29          idem
004063D1	         Trial
0040957E          I nvalid Unlocking Code
0040751F	         The serial entered is incorrect
00407ACC         Thank You for purchasing
00407684           idem
00406241          Thank you for Trying
004094E1 et 00409485
no occurrence

There are several others reference, but these one shows that there is somewhere a Registration Box!

But where is it?

You cannot have the access to it by one of the menus of the target, and no keyboard's combinations seems to popup it (remember one of the first versions of WinZip, you need to do a CRTL-R for acceded to the Reg. Box).

It is here!

While the are many references in W32dasm, you have several "Buy Now", a strange reference: Turnkexe (see the Goth's essay about SalesAgent 3.0), all that after a TRIAL's string.

And if we begin to have a look just a little bit before this one?

Application n°1

:00406386 8B842430010000          mov eax, dword ptr [esp+00000130]
:0040638D 3D10010000              cmp eax, 00000110
:00406392 0F8733040000            ja 004067CB -> 2 tests here
:00406398 7418                    je 004063B2
:0040639A 83F80F                  cmp eax, 0000000F
:0040639D 0F84FD060000            je 00406AA0
:004063A3 33C0                    xor eax, eax
:004063A5 5F                      pop edi
:004063A6 5E                      pop esi
:004063A7 5D                      pop ebp
:004063A8 5B                      pop ebx
:004063A9 81C418010000            add esp, 00000118
:004063AF C21000                  ret 0010

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:004063B2 A100124400              mov eax, dword ptr [00441200]
:004063B7 85C0                    test eax, eax
:004063B9 751E                    jne 004063D9
:004063BB A1C0E74300              mov eax, dword ptr [0043E7C0]
:004063C0 85C0                    test eax, eax
:004063C2 7415                    je 004063D9
:004063C4 A1A0BE4300              mov eax, dword ptr [0043BEA0]
:004063C9 8D8C24A4000000          lea ecx, dword ptr [esp+000000A4]
:004063D0 50                      push eax

* Possible StringData Ref from Data Obj ->"%s Trial"
:004063D1 68A4C74200              push 0042C7A4
:004063D6 51                      push ecx
:004063D7 EB14                    jmp 004063ED

* Possible Reference to Dialog: DialogID_07DB, CONTROL_ID:03F0, "&Buy Now"
:0040647B 68F0030000              push 000003F0

* Possible StringData Ref from Data Obj ->"Essai"
:00406486 6898C74200              push 0042C798

* Possible Reference to String Resource ID=00001: "Turnkexe"
:0040648B 6A01                    push 00000001

Application n°2:

:00406376 8B8424DC000000          mov eax, dword ptr [esp+000000DC]
:0040637D 3D10010000              cmp eax, 00000110
:00406382 0F87AA030000            ja 00406732 -> we found the same scheme!
:00406388 7418                    je 004063A2
:0040638A 83F80F                  cmp eax, 0000000F
:0040638D 0F8474060000            je 00406A07
:00406393 33C0                    xor eax, eax

A comparison with 110, and a jump if greater as, or jump if = as.
We are in 00406382, and we can jump at 00406732, 350 bytes away: a little longer, no?
Go to see what it is, by changing the ja 00406732 with a jmp 00406732.

:00406732 3D11010000              cmp eax, 00000111
:00406737 0F84F7000000            je 00406834
:0040673D 3D06020000              cmp eax, 00000206
:00406742 7463                    je 004067A7
:00406744 3D11030000              cmp eax, 00000311
:00406749 0F851A030000            jne 00406A69
:0040674F 6A00                    push 00000000
:00406751 6A00                    push 00000000
:00406753 53                      push ebx

Remember the +ORC's teaching (contribution of Psyché)

:0040612A 56                      push esi
:0040612B 6850634000              push 00406350 <- address of the routine WinProc
:00406130 50                      push eax

* Possible Reference to Dialog: DialogID_0076 
:00406131 6A76                    push 00000076 -> N° of the dialog define by the programmer
:00406133 8935C8124400            mov dword ptr [004412C8], esi
:00406139 51                      push ecx
:0040613A EB15                    jmp 00406151 
-> call of dlgboxparam / in red, it's the necessary API (see the API ref)

* Reference To: USER32.DialogBoxParamA, Ord:008Eh
:00406151 FF1588954400            Call dword ptr [00449588]

So, we land here every time it append something with the dlgbox

:00406350 A128694300              mov eax, dword ptr [00436928]
:00406355 81EC18010000            sub esp, 00000118

* Reference To: USER32.GetDlgItem, Ord:00F3h
:00406367 8B3584954400            mov esi, dword ptr [00449584]

* Reference To: USER32.EnableWindow, Ord:00B2h
:0040636E 8B3DE8954400            mov edi, dword ptr [004495E8]

* Possible Reference to String Resource ID=00001: "Turnkexe"
:0040637E 6A01                    push 00000001

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:00406386 8B842430010000          mov eax, dword ptr [esp+00000130]
:0040638D 3D10010000              cmp eax, 00000110

In eax you can found the "event" of the dlgbox send by Windows, here 110 = WM_INITDIALOG, It's means that the window is begin to be created. It will be important to know if the window (dlgbox) is ended or not. If not: continue if creation => je 4063b2
The ja make reference at all were greater as 110, like a very important: 111 = WM_COMMAND -> ja 4067CB, in other terms, when there are an event on the window.

* * * * * *

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:004067CB 3D11010000              cmp eax, 00000111
:004067D0 0F84F7000000            je 004068CD

* * * * * *
We land here if there are a click and it is the part where decide which button of been selected...
This information is took on the stack, and putting in ecx, and after in eax
The values important are 3EF 3EE and 3ED, who must be the code for a EXIT Button, or the equivalence, while it send to a ENDDIALOG which destroy the dlgbox created before (the handle were in ebx).

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:004068CD 8B8C2434010000          mov ecx, dword ptr [esp+00000134]
:004068D4 8BC1                    mov eax, ecx
:004068D6 25FFFF0000              and eax, 0000FFFF

* Possible Reference to Dialog: DialogID_07DB, CONTROL_ID:03EF, ""
:004068DB 3DEF030000              cmp eax, 000003EF

* Reference To: USER32.EndDialog, Ord:00B4h
:004068F1 FF1594954400            Call dword ptr [00449594]

Go back to our last jump!

A look in the Dead Listing, this address goes on Turnkexe, and on the Control_ID of Buy Now...
Inversion of the Zero Flag, and F5 to see the result...

Now, the Shareware screen popup whit a new button: Buy Now. Ah! Ah!
Is my Reg. Box behind this button?

And YES!
By now, the scheme of the Reg. Box will be the same as the previous target:


* Reference To: USER32.GetDlgItemTextA, Ord:00F5h
:1000B396 FF15B8950310            Call dword ptr [100395B8] -> you are here 
:1000B39C BFD0B50210              mov edi, 1002B5D0 -> your serial in EDI 
:1000B3A1 83C9FF                  or ecx, FFFFFFFF
:1000B3A4 33C0                    xor eax, eax
:1000B3A6 F2                      repnz
:1000B3A7 AE                      scasb
:1000B3A8 F7D1                    not ecx
:1000B3AA 49                      dec ecx
:1000B3AB 83F90A                  cmp ecx, 0000000A 
-> This code is 10 characters long ?
:1000B3AE 743B                    je 1000B3EB
:1000B3B0 8B1554180310            mov edx, dword ptr [10031854]

* Possible StringData Ref from Data Obj ->"Sorry, that unlocking code is "
                                        ->"not valid for this program."
:1000B3B6 6898180210              push 10021898

Before beginning the tracing by F10, you must put a BPM EDI. If you step on a call which solicit the code entered, you will know that immediately.
At each break, asked the register and search the echo of the good serial. When you arrive here, you can tell you that it's happen something:


:1001FD4C 0AC0                    or al, al
:1001FD4E 742E                    je 1001FD7E
:1001FD50 8A06                    mov al, byte ptr [esi] -> a character of ESI in Al
:1001FD52 46                      inc esi                -> prepare the next character
:1001FD53 8A27                    mov ah, byte ptr [edi] -> character of EDI in Ah
:1001FD55 47                      inc edi                -> prepare the next character
:1001FD56 38C4                    cmp ah, al -> compared a character of ESI with a character of EDI
:1001FD58 74F2                    je 1001FD4C-> the next lines check the validity alpha numeric of your serial
:1001FD5A 2C41                    sub al, 41             -> letter A
:1001FD5C 3C1A                    cmp al, 1A               
:1001FD5E 1AC9                    sbb cl, cl
:1001FD60 80E120                  and cl, 20             -> space
:1001FD63 02C1                    add al, cl
:1001FD65 0441                    add al, 41

And for the other application:

:100203F0 8A06                    mov al, byte ptr [esi]
:100203F2 46                      inc esi
:100203F3 8A27                    mov ah, byte ptr [edi]
:100203F5 47                      inc edi
:100203F6 38C4                    cmp ah, al 

if they are a moment when you must do a "d edi", it's now:

And in the Data's window, you have:

00 00 ................
00 00 0007467361......
00 00 489335..........
00 00 HDWCNECCIY......
00 00 ................

489335, is the number i've entered. After a conversion in hexadecimal, it gives 7777. By this way, if one of the registers get it, I'll see it immediately by having an eye on the good window.
And the two other codes, one numerical, the other alphabetical?
We have seen that the entered code must be 10 characters: The two answer at this need.
So, what is the good one?
In fact, when the reg. Box option is active, the Alphabetical Unlock Key is used for the first DialogBox, and the numerical for the second Reg. Box . Double protection!

When you asked the Sting Data references, you can see a sting like: PYUXAHLLRQ.

* Possible StringData Ref from Data Obj ->"PYUXAHLLRQ"
:004097B4 BD34D64200              mov ebp, 0042D634
:004097B9 83C408                  add esp, 00000008
:004097BC 2BF1                    sub esi, ecx
:004097BE 2BF9                    sub edi, ecx
:004097C0 2BE9                    sub ebp, ecx
:004097C2 2BC1                    sub eax, ecx
:004097C4 89442424                mov dword ptr [esp+24], eax
:004097C8 C74424200B000000        mov [esp+20], 0000000B

Good serial Number? Anti-piracy test?

Well, as i've said, i've search the good serial in SoftIce, and i've not entered this one

We are all a little paranoiac! And i've been afraid to fall on an Anti piracy number, the kind of serial which kill your application directly. (GetRight, a very good program used some Catch-piracy like this one, but with no consequence instead of a DialogBox...).

Well! Entered the codes you have found:

* Possible StringData Ref from Data Obj ->"This file contains your registration "

->"name and serial number for %s."

And you can saw a box: "Your payment was successfully completed", then a screen "Transferring Files" or someone like this. The loader of the target begin is work of discompression of the file Dl_, and ended by erasing all traces of the Time Trial. The program makes an auto patching.

In this version of this Read Made Protection, they are no double RegBox, just while the Distributor of the shareware has not selected this option.

The Third Option:

How to Enable the Try Button when it has not been configured

When I have beginning the reverse engineering of the next target, I just dispose of SoftIce and Hiew. I already know the Principe of the protection, but without having under the hand the necessary tools for searching the Lock key (Wdasm, Filemon, and Regmon)

After the Lock Key have been placed, the target has screened "Due to Security"

By putting a Bpx DialogBoxparamA, I'll land in these lines, you have already seen:

0137:004149ED  FF15D4224300        CALL    [USER32!DialogBoxParamA]
0137:004149F3  A1ECFF4400          MOV     EAX,[0044FFEC]
0137:004149F8  85C0                TEST    EAX,EAX
0137:004149FA  7443                JZ      00414A3F
0137:004149FC  A110004500          MOV     EAX,[00450010]
0137:00414A01  50                  PUSH    EAX

Usually, after this Dialogbox, the shareware screen popup with the try button disabled.

A the end of the call, you'll be here:

0137:004063CD  6810004500          PUSH    00450010
0137:004063D2  51                  PUSH    ECX
0137:004063D3  E858E40000          CALL    00414830
0137:004063D8  68E49B4300          PUSH    00439BE4  > here
0137:004063DD  8BF0                MOV     ESI,EAX
0137:004063DF  E8CCE30000          CALL    004147B0
0137:004063E4  83C418              ADD     ESP,18

When tracing a little, since the address 004063D8, you'll be landed in these lines:

0137:004064D8 8B442414 MOV EAX,[ESP+14]
0137:004064DC 83C0FE ADD EAX,-02
0137:004064DF 83F81E CMP EAX,1E > 1E for 30 days?
0137:004064E2 0F8742060000 JA 00406B2A > no jump
0137:004064E8 33C9 XOR ECX,ECX
0137:004064EA 8A88786B4000 MOV CL,[EAX+00406B78]
0137:004064F0 FF248D646B4000 JMP [ECX*4+00406B64]
If you replace the JA 00406B2A by a jmp, the shareware screen wills active the Try Button.

One modification at this stair will permit you to have the eternal benefice of the program on his actual state, but go on:

By tracing, you will finish to see the shareware screen with his Try Button grayed, and his Cancel Button. The Bpx DialogBoxparamA will, an other time, help us to land here:

0137:00406B1A  FF15D4224300        CALL    [USER32!DialogBoxParamA]  > nag
0137:00406B20  8BF0                MOV     ESI,EAX
0137:00406B22  891D542E4400        MOV     [00442E54],EBX
0137:00406B28  EB04                JMP     00406B2E
0137:00406B2A  8B74240C            MOV     ESI,[ESP+0C]
0137:00406B2E  83FE02              CMP     ESI,02  > If cancel button clicked?
0137:00406B31  891DA8DE4400        MOV     [0044DEA8],EBX
0137:00406B37  0F85B7FDFFFF        JNZ     004068F4  > end of the program
0137:00406B3D  5E                  POP     ESI
0137:00406B3E  5D                  POP     EBP

In 0040B6B2E, ESI contain 2 if the Cancel Button is clicked, and the application ended. In the other way, by default, the Target started. So, when replacing the JNZ 004068F4 by a JZ, you have a new solution to launch the program, however the presence of the Lock Key in the register Base. It's not very elegant... and there is always the screen "Due to security" who make a little negligée.

How to erase the first DialogBox

The DialogBox "Due to security" could be bypassed by much ways:

  1. modifying the jump in 004149A5

  2. nopping the call 00414830 at 004063D8(Yes, I know...). This call can be nopped without problem, but one more time, this solution is not very elegant. We can found better later!
:00414996 68F07D4300              push 00437DF0
:0041499B E820FEFFFF              call 004147C0
:004149A0 83C404                  add esp, 00000004
:004149A3 85C0                    test eax, eax
:004149A5 740E                    je 004149B5   > here
:004149A7 5F                      pop edi
:004149A8 B825400000              mov eax, 00004025
:004149AD 5E                      pop esi
:004149AE 81C480020000            add esp, 00000280
:004149B4 C3                      ret
:004149B5 68FF0F0000              push 00000FFF
:004149BA 6858374500              push 00453758
:004149BF 6833010000              push 00000133
:004149C4 C705FC02450001000000    mov dword ptr [004502FC], 00000001
:004149CE E85DFDFFFF              call 00414730
:004149D3 8B9424A4020000          mov edx, [esp + 000002A4]
:004149DA 83C40C                  add esp, 0000000C
:004149DD 6A00                    push 00000000
:004149DF 52                      push edx
:004149E0 6A00                    push 00000000
:004149E2 6834020000              push 00000234
:004149E7 E884FDFFFF              call 00414770
:004149EC 50                      push eax
:004149ED FF15D4224300            Call [USER32!DialogBoxParamA] > nag
:004149F3 A1ECFF4400              mov eax, [0044FFEC]
:004149F8 85C0                    test eax, eax
:004149FA 7443                    je 00414A3F
:004149FC A110004500              mov eax, [00450010]
:00414A01 50                      push eax
:00414A02 E84989FFFF              call 0040D350

How to erase the second DialogBox

By nopping the call 00414830, you don't go in the procedure who verify the "Due to security", and the values in the registers will permits you to go trough the next tests without problem, started the application without the Shareware Screen, and without other modification.

0137:0040B698  7554                JNZ     0040B6EE  >(NO JUMP)
0137:0040B69A  6844CD4300          PUSH    0043CD44
0137:0040B69F  E81C910000          CALL    004147C0
0137:0040B6A4  83C404              ADD     ESP,04
0137:0040B6A7  85C0                TEST    EAX,EAX
0137:0040B6A9  7427                JZ      0040B6D2
0137:0040B6AB  6804010000          PUSH    00000104
0137:0040B6B0  8D8538FEFFFF        LEA     EAX,[EBP-01C8]
0137:0040B6B6  50                  PUSH    EAX
0137:0040B6B7  E8F496FFFF          CALL    00404DB0
0137:0040B6BC  83C408              ADD     ESP,08
0137:0040B6BF  85C0                TEST    EAX,EAX
0137:0040B6C1  740F                JZ      0040B6D2
0137:0040B6C3  8D8D38FEFFFF        LEA     ECX,[EBP-01C8]
0137:0040B6C9  51                  PUSH    ECX
0137:0040B6CA  E88192FFFF          CALL    00404950
0137:0040B6CF  83C404              ADD     ESP,04
0137:0040B6D2  685CCD4300          PUSH    0043CD5C
0137:0040B6D7  E8D4900000          CALL    004147B0
0137:0040B6DC  83C404              ADD     ESP,04
0137:0040B6DF  6A00                PUSH    00
0137:0040B6E1  E8AAACFFFF          CALL    00406390  > go to "due to security"
0137:0040B6DF 6A00 PUSH 00
0137:0040B6E1 E8AAACFFFF CALL 00406390 > go to "due to security"

A modification of the jump at 0040B698 will be more satisfied, as the savage Nopping of the call 04036E1: the result is the same...

You just have to modify the program at 0040B698!

And with just that, the protection is over.

It is at this time, that SoftIce had crashed for the second time!

The two tests, i've attach with the checksum have been crossed without any difficulty, but a little more ahead:

0137:00419C1E  5E                  POP     ESI
0137:00419C1F  C70064000000        MOV     DWORD PTR [EAX],00000064 > Oups!
0137:00419C25  5B                  POP     EBX
0137:00419C26  7409                JZ      00419C31
0137:00419C28  50                  PUSH    EAX
0137:00419C29  E8D2630000          CALL    00420000
0137:00419C2E  83C404              ADD     ESP,04

Break due to general protection fault!!!

I'll be aware of this reaction, since i've already seen it, and at the SAME place in other Target!

In other place, i've resolved the problem like this way:

Application n°1:

Possible Reference to String Resource ID=00100:
->  "Please choose to buy the software or click on Cancel to exit"

:00401CD3 C70064000000            mov dword ptr [eax], 00000064
:00401CD9 7409                    je 00401CE4
:00401CDB 50                      push eax
:00401CDC E86FDC0100              call 0041F950
:00401CE1 83C404                  add esp, 00000004

By inverting the lines 00401CD3 and 00401CD9

:00401CD3 740F                    je 00401CE4
:00401CD5 C70064000000            mov dword ptr [eax], 00000064
:00401CDB 50                      push eax
:00401CDC E86FDC0100              call 0041F950
:00401CE1 83C404                  add esp, 00000004

(it is interesting to tell you that my hexeditor have found 72 times the SAME routine, when using Find/Replace: a surprise!)

Well, you just have to replace C700640000007409 by 740FC70064000000

And modifying the jump which go to the security control:

:00408B11 E8BAD3FFFF              call 00405ED0
:00408B16 83F8FF                  cmp eax, FFFFFFFF
:00408B19 55                      push ebp
:00408B1A 750B                    jne 00408B27


:00408B11 90                      nop
:00408B12 90                      nop
:00408B13 90                      nop
:00408B14 90                      nop
:00408B15 90                      nop
:00408B16 83F8FF                  cmp eax, FFFFFFFF
:00408B19 55                      push ebp
:00408B1A EB0B                    jmp 00408B27 

The end is not far away

But for this target, the scheme is not totally the same, and no inverting is possible. So i've nopped (hey!) the nasty line to be able to continue (Indian1998+ had made the same, like he explain it in this essay about Adobe Image Read)

After a new try, the third Crash will be here:

0137:00416F72  5E                  POP     ESI
0137:00416F73  C70064000000        MOV     DWORD PTR [EAX],00000064 > Re Oups!
0137:00416F79  5B                  POP     EBX
0137:00416F7A  7409                JZ      00416F85
0137:00416F7C  50                  PUSH    EAX
0137:00416F7D  E87E900000          CALL    00420000

And Nop Nop Nop Nop Nop Nop a new time, F5, and the soft begin quietly...


There are 3 modifications that must be made:

0137:0040B698  7554     JNZ     0040B6EE
must be replaced by
0137:0040B698  7454     JZ      0040B6EE
0137:00419C1F  C70064000000        MOV     DWORD PTR [EAX],00000064 

and at
0137:00416F73  C70064000000        MOV     DWORD PTR [EAX],00000064
you can replaced it by Nop

(Note that you found 37 occurrences on this string)

There is other solution to go around this checksum:

How to disable the checksum without nopping the mov [eax],64?

If there are many occurrences on this mov dword ptr [eax], 00000064, at each time just two of them are solicited and give a "break due to general protection fault.

With the help of the disassembled listing, it's quick to see that these two addresses are one upper the second in the same call:

* Referenced by a CALL at Address:
:00404540 81EC20010000          sub esp, 00000120
:00404546 8D442420              lea eax, [esp + 20]
:004045CF 0FAFC6                imul eax, esi
:004045D2 83C404                add esp, 00000004
:004045D5 85C0                  test eax, eax
:004045D7 C70064000000          mov dword ptr [eax], 00000064  > here
:004045DD 7409                  je 004045E8
:0040466C 0FAFC6                imul eax, esi
:0040466F 83C404                add esp, 00000004
:00404672 85C0                  test eax, eax
:00404674 C70064000000          mov dword ptr [eax], 00000064  > and here

Down, you can see than there are no push before the nasty call,
and no parameters are send inside its.

:00404814 A4                    movsb
:00404815 E856E00000            call     00412870
:0040481A 8A4801                mov cl,  byte ptr [eax+01]
:0040481D 83C408                add esp, 00000008
:00404820 3ACB                  cmp cl,  bl
:00404822 7403                  je       00404827
:00404824 885801                mov byte ptr [eax+01], bl

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:00404827 E814FDFFFF            call     00404540 ***here****
:0040482C 33FF                  xor edi, edi
:0040482E 891D745D4200          mov dword ptr [00425D74], ebx
:00404834 C705805D4200B0114000  mov dword ptr [00425D80], 004011B0

So, we can simply write a RET on the first line of these procedure anti-crack of XXXpop.exe
And replace
:00404540 81EC20010000 sub esp, 00000120
:00404540 C3 RET 

How can we oblige the protection to transform all Shareware in full version?

If you click on the icon of XXXpop.exe, you will saw a screen with "Please wait while you software is being prepared", and immediately after a Message box "You cannot Run this application a this time".


To see what it could result, and if a jump couldn't make the difference, i've beginner to put a Bpx MessageBoxA in SoftIce.

At the next time, and after the "please Wait..." SoftIce has made a break. F12 to go out this call, popup of the message box "You cannot run...", click on the button [OK], and you will be back in SoftIce, in 00404D9C.

* Reference To: KERNEL32.SleepEx, Ord:0240h
:00404D4B FF15E8624300            Call dword ptr [004362E8] > launch "Wait…"
:00404D51 E8DAF9FFFF              call 00404730             > eax=0 at the exit
:00404D56 8B1D70644300            mov ebx, [00436470]  
:00404D5C 8BF0                    mov esi, eax
:00404D5E 83FEFF                  cmp esi, FFFFFFFF 
:00404D61 7504                    jne 00404D67              > jump over the call ebx 
:00404D63 6A00                    push 00000000
:00404D65 FFD3                    call ebx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:00404D67 8B3D98644300            mov edi, [00436498]      > push "You cannot run…"
:00404D6D 85F6                    test esi, esi
:00404D6F 752F                    jne 00404DA0             > could jump over the call edi (no jump)

* Possible StringData Ref from Data Obj ->"You cannot run this application
                                        ->"at this time."
:00404D71 6804024200              push 00420204
:00404D76 68408B4200              push 00428B40
:00404D7B E880DA0000              call 00412800
:00404D80 8B8C2458050000          mov ecx, [esp + 00000558]
:00404D87 83C408                  add esp, 00000008
:00404D8A 6830000100              push 00010030

* Possible StringData Ref from Data Obj ->"WARNING"
:00404D8F 68FC014200              push 004201FC
:00404D94 68408B4200              push 00428B40
:00404D99 51                      push ecx
:00404D9A FFD7                    call edi  > popup "You cannot run…"
:00404D9C 6A00                    push 00000000

You have two jumps, over the Call EDI, but just one can goes away the line 00404D9A.
1er reflex, seeing if after an inversion of the zeroFlag, the program will continued in the direction of the discompression module...

XXXpop.exe always screened "Please wait...", but you must make a Ctrl-Alt-Suppr to kill the task.

It will be to pretty!
Well, seeing now what can append by making a R register = X, before the test, and with a R FL Z, we could have some more chance...

Not Better!
By appearance, the registers must contain some others values, or the calls 00404730, EBX and 00412800 places in memory addresses some values waiting a little bit latter.

With an already discompressed copy of a full version (see upper), and with a shareware copy of dl_, i've continued my research.

This time, I am searching what can be different between this two copy, and found what can be wrong in my idea.
FileCompare, is a good tool for this kind of job.
After the disassembling of this two copy in Wdasm32, i've obtain 2 listings that i've compared one with the other, with FileCompare.

More than 40 pages, and with 60 lines per pages, I will be confronted to 2400 modifications...

Motivated, but not mad...

Well, other way that must be falling out.

Finally, I decide to go back to my first study of the registers, and i've forced xxxPOP.exe to discompresse a file dl_, by using the register box, with all my breakpoints on.
After Rsagnt32.dll had finished his job, it gives the hand to xxxPOP.exe, and the screen "Please wait..." popup.


Break at 00404D51. Now, I don't have the right to make a mistake: if I don't found now the differences between the two files, I have no more solutions...

Too lazy to visit all the different calls, and notes all the changes in the registers, i've been just interesting by the value of this one at the exit of the 3 calls, and particularly before the jump at 00404D61 and 00404D6F.

Here is the result:
EAX and ESI must have the same value (01) before the first test at 00404D61, instead of the zeros , i've before.

Little essay on other file xxxpop.exe.
By making the same thing (Bpx MessageBoxA, Bpx on the first test after the call[KERNEL!SleepEx]), i've changing the value in the registers EAX and ESI (01).

Discompression begin...

Well, what must I do now, at 00404D56 I have a MOV ESI, EAX. And a comparison between ESI and -1

:00404D56 8B1D70644300 mov ebx, [00436470]
:00404D5C 8BF0 mov esi, eax
:00404D5E 83FEFF cmp esi, FFFFFFFF
:00404D61 7504 jne 00404D67

All go as I whish in memory. Now the change is made with the help of my hexeditor.

00404839C TEST EAX EAX
00404839E MOV DWORD PTR [EAX], 00000064
0040483A4 JZ 004083AF

It's the same problem as upper, and you have certainly recognized the manifestation of the sort of checksum, already seen. To solve the problem, you just have to do:

00404839C TEST EAX EAX
004083A4 JZ 004083AF (jump)
004083A6 MOV DWORD PTR [EAX], 00000064

The JZ jump, the MOV is not yet a matter. Second essay...

Second Crash at 0040843F, and a new time a MOV DWORD PTR [EAX], 00000064.
Nop it, or do the same thing as upper, and don't tell me about it!

Started XXXPOP.exe, and you will have a nice discompression at the key.

Can this solution work for all targets?

Yes and No!
This patch will be good for some targets, but not for every POP file.

Can we found a common solution?

At first time, you have to disable the checksum by nopping, or changing all Mov Dword Ptr [eax], 00000064.
For that, you will need a hexeditor, and replace C70064000000 by NOP (don't be surprise, you can have more than 70 occurrences that could be changed).

After ?

A other common point at all the POP's file, is this addresses already seen:

:00404D56 8B1D70644300 mov ebx, [00436470]
:00404D5C 8BF0 mov esi, eax
:00404D5E 83FEFF cmp esi, FFFFFFFF
:00404D61 7504 jne 00404D67

Or, in two of the studding case:

:00404COE FF1564A04100 call [kERNEL32!SleepEx] > "Please Wait..."
:00404C14 E8D7F9FFFF call 004045F0 > controles
:00404C19 83FEFF (line to change) cmp eax, FFFFFFFF > if eax = -1
:00404D61 7504 jne 00404D67 > go on

And we know that EAX must be = at 01 before the test at 00404D61 or 00404C19

By replacing

:00404D56 8B1D70644300 mov ebx, [00436470]
:00404D5C 33C0 xor eax, eax > eax = 0
:00404D5E 40 Inc eax > eax=eax+1
:00404D5F 8BF0 mov esi, eax > esi = eax
:00404D61 7504 jne 00404D67 > jump or no jump, no matter

By now, all program protected by this Ready Made protection could be solved by the same patch!


FACE="Courier New">