TORN@DO presents: cRACKER's n0TES
Commerical Protection Systems: SalesAgent


SalesAgent 3.0 BUY NOW Cracking (Goth)
Well, I assume that you've taken all obligatory precautions (backup the registry and such ...), installed our target and restarted Win95.

PART I - Look what the cat dragged in
First you'll see how our target behaves. Start your program. You'll get the usual 'Time Trial' window. We won't bother to 'Try first' head right to 'Buy now'. Fill in some stuff and push 'Next' until you reach the 'Select Payment Method' window. Now, do you have your credit card info handy? If not, you should reverse our target to see which numbers are valid or visit some fancy hacker site and get a credit card generator (e.g. CreditMaster) or simply enter:



    Card:    American Express
    No.:     00000000
    Exp.:    01/05
    Name:    Goth
    
And push 'Next' until you get to the 'Select Communication Methods" window. For various reasons it's necessary to make sure you CAN'T connect to anything, switch off your modem, cut your cable or whatever and push 'Next'. Oops, unable to connect and so on. Cancel the whole 'Buy now' thing.

Now, you could observe our target with trial period expired. But you all know what will happen, don't you? Yes, the 'Try first' button will vanish and it WON'T come back if you set your RTC back. Well, it's a time trial. So at this point you could have the bright idea to fire up SoftICE, bpx GetSystemTime, track down the bytes to patch in the EXE/DLL and ready you are.

- NO YOU DON'T!

What you'll do at this point is pushing 'Buy now' again. (Sometimes when I get these strange attacks of dumbness, I can't believe there's a 'Buy now' button but no way to enter any registration code or such and I'll try again... ;-)


You see all fields of your 'User Registration' window filled with information you've entered before. Close the program and start again. Info is still there. SalesAgent stores user info somewhere!



PART II - The Anatomy of SalesAgent 3.0
You should now examine our target's files to get a rough overview of what's going on. Well, five should be more than enough I took a deep look at RSAGNT32.DLL. Use BRW and/or W32dasm. Look at the import and export tables, resources, headers and so on ... Check if they're encrypted/compressed. Use your imagination. What file can perform what task? How does the scheme work? FEEL it ...

Having felt enough you should come at least to these results:


- If your program has more than one EXEs, they all have the same size
  => can't be the real EXEs => some kind of loader

- ********.DL_s are encrypted => the real EXEs will be loaded, decrypted, whatever ... RSAGNT32.DLL connects to internet server, contains resources for ENTERING REGISTRATION CODE


Now, how does our start process look like?
You start the program which uses RSAGNT32.DLL to check if you're in your trial period and then presents the 'Trial' window. If you push 'Try first' the encrypted DL_ is being temporary decrypted and started. If you push 'Buy now' the RSAGNT32.DLL is used for getting user information, internet connection and REGISTRATION. After registration the *.DL_ files should be permanently decrypted.

So how do we get RSAGNT32.DLL to let us register?



PART III - Faking a mail/fax order I've used W32Dasm to disassemble RSAGNT32.DLL. First I examined it's import table to see what it is able to and to look for suspicious imports. Huh, you'll find a lot. What should make your bells ring is that it's able to modify registry entries but also uses the absolete PrivateProfileString (*.INI) stuff. This needs further investigation.

W32dasm finds the first appearance of GetPrivateProfileStringA here:



    ...
    * Reference To: KERNEL32.GetPrivateProfileStringA, Ord:0112h
      
                                       |
    :100015EE   8B35A8010210 mov esi, dword ptr [100201A8]
      
    * Possible StringData Ref from Data Obj ->"rsagent.ini"
      
                                       |
    ...
    
Oops, it tries to read from a file called RSAGENT.INI And where are these *.INI thingies usually kept? Right, we'll find it in our 'Windows' directory:

[ReleaseSoft]
firstName=Goth
lastName=Nosferatu
company=!
street1=!
street2=!
city=!
state=
zip=12345
country=United States
geoType=110
phoneNum=!
faxNum=!
email=!
personalCode=
toneDial=1
callWait=0
needAccess=0
accessCode=9
intlPrefix=
callWaitStr=
mailStat-975135=0
ATTN=AT
MTONEDIAL=T
PULSEDIAL=P
DIALTHIS=D
WORDRESULT=V1
HANGUP=H0
ADDINIT=E0
ESCAPE=+++
OKAY=OK
NOCARRIER=NO CARRIER
CONNECTED=CONNECT
NODIALTONE=NO DIALTONE
BUSY=BUSY

It wasn't there right after the installation. So it must have been created while we tried to register the target in PART I. Examine it. Look for something that could help us to register. Well, till 'email=!' (Yes, I'm a lazy bastard. I entered all these '!') nothing of importance. But wait, 'personalCode='!

Where have we seen this before? If you did as I told you in PART II you would know where. Use BRW. Look at dialog 2011! What is this dialog's title? 'Complete Mail / Fax Payment'! Hm, Mail?, Fax? can't remember any Mail / Fax order opportunity during 'Buy now' procedure. Take a look at dialog 2001. Our old friend from PART I 'Select Communication Method' but this dialog allows ordering by phone and mail/fax. So it should be possible to get to dialog 2011 without completing the internet/modem connection!

All entries are pretty self explainary but what's about this 'mailStat-975135=0' entry? Let's change it to 1, restart NU and try 'Buy now' procedure again. Anything changed? Of course! We are finally at dialog 2011. There we have a 'Personal Code' and what we haven't is an 'Unlocking Code'. But not for long ...



PART IV - RSAGNT32.DLL's builtin KeyGenerator
We know that our 'Unlocking Code' will be recieved by dialog 2011. So you should bpx GetDlgItemTextA in SoftICE. Enter a dummy unlock code (e.g. gothtog) and after pressing F12 SoftICE will popup here
:


    :10005612    mov edi, 10032E20              <= our unlocking code
    :10005617    or ecx, FFFFFFFF
    :1000561A    xor eax, eax
    :1000561C    repnz
    :1000561D    scasb
    :1000561E    not ecx
    :10005620    dec ecx
    :10005621    cmp ecx, 0000000A              <= is it 10 chars long?
    :10005624    je 10005665                    <= Yes! => Go for validation check!
    :10005626    lea edx, dword ptr [esp+10]    No! => ...
      
    * Possible StringData Ref from Data Obj ->"Sorry, that unlocking code is not valid for
    this program."
                   
                                                         |
    :1000562A    push 10023890
    :1000562F    push edx
    :10005630    call 10014590
    
Step over the next instructions, toogle zero flag at 10005624 and step on till you reach:


    :100056A8    push ecx
    :100056A9    push edx
    :100056AA    push eax
    :100056AB    call 1000B980                  <= calculate the real code
    :100056B0    add esp, 0000000C
    :100056B3    lea ecx, dword ptr [esp+000000D8]
    :100056BA    push 10032E20                  <= our code
    :100056BF    push ecx                       <= real code
    :100056C0    call 1001F5C0                  <= compare
    :100056C5    add esp, 00000008
    :100056C8    test eax, eax                  <= if compare fails (eax!=0)
    :100056CA    jne 1000597C                   <= we'll get 'Sorry, that...'
     ...         ...
    
At 100056BA we dump ecx and get a perfect 10 chars long unlock code like: 'RQXKNKQJPP' (This code is only valid if your personal code was '1234567890' and the program was Dreamweaver! BTW, you the unlock codes changes if you modify your 'personalCode' entry and your 'mailStat-975135' in RSAGENT.INI!) Leave SoftICE (F5). Enter the unlock code and we get a 'Enter your serial' window. (Weird!) Here we enter our unlock code again and it's done!



PART V - Summary and Additions
We won't have to deal with any encryption routines since SalesAgent 3.0 can be defeated in less than 2 min:


- change 'personalCode=' to 'personalCode=1234567890' and 'mailStat-975135=0' to 'mailStat-975135=1' in RSAGENT.INI (if there's no RSAGENT.INI create one!)

- start the 'Buy now' procedure and

- enter 'RQXKNKQJPP' as unlock code (only if your cracking Dreamweaver)




SalesAgent 3.0 TRY FIRST Cracking (Victor Porguen)
Back in the 'old days' we used to create reasonably deceptive viruses that used 'stealth' techniques to hide code changes from CRC and integrity checkers. Simply put, when the integrity checking routine opened the file, or made a file read, the viral code would substitute the correct code in place of the modified code thus preventing detection regardless of the complexity of the CRC algorithm. This same concept can be applied to cracking time limited programs that go to the trouble of checking the integrity of the executable from the disk file (as opposed to checking the code while it is in memory).

Programs protected by SalesAgent's can have the common x-day Try-Buy interface that we have all grown to know and love. An example of this could be WinFAX Pro 9.0 from Symantec, which is the example program for this essay. Cracking the date limitation while SoftICE is loaded in memory is a rather trivial exercise. Nevertheless we must first address the actual 'crack' before we can examine the more interesting aspect of defeating the file integrity check. The usual methods of tracing through the code, setting appropriate breakpoints, and so forth will lead you to the routine that awaits the 'click' on either the 'Buy Now', 'Try First' or 'Cancel' option - of course, the 'Try First' option is disabled after 30 days. One of the simplest methods for locating this area of code is to place a breakpoint on DialogBoxParamA. When SoftICE pops up, F11 will execute the CALL, click on 'Try First' and SoftICE will pop up once more, and then F12 will break on the RETurn out of the subroutine, which will be OFFSET 00408BA7. You will now be sitting smack dab in the middle of the date checking routine and the necessary crack should be readily apparent. Here is the disassembly:



      :00408B75 A3E8864300            MOV      [004386E8],EAX 
      :00408B7A 892D14864300          MOV      [00438614],EBP 
      :00408B80 E84B960100            CALL     004221DO 
      :00408B85 83C408                ADD      ESP,08 
      :00408B88 85CO                  TEST     EAX,EAX 
      :00408B8A 751D                  JNZ      00408BA9 
      :00408B8C 6868044300            PUSH     00430468 
      :00408B91 68A0834300            PUSH     004383AO 
      :00408B96 E835960100            CALL     004221DO 
      :00408B9B 83C408                ADD      ESP,08 
      :00408B9E 85CO                  TEST     EAX,EAX 
      :00408BAO 7507                  JNZ      00408BA9 
      :00408BA2 E809D5FFFF            CALL     004060BO 
      :00408BA7 EB05                  JMP      00408BAE 
      :00408BA9 B801000000            MOV      EAX,00000001 
      :00408BAE 83F8FF                CMP      EAX,-01 
      :00408BBI 55                    PUSH     EBP 
      :00408BB2 7514                  JNZ      00408BC8 
      :00408BB4 FF1540D24200          CALL     [USER32!PostQuitMessage] 
    
A two second review of this disassembly reveals the fact that if the program executes the instruction at 00408BA9 there will be no expiration of the program. Further, if the program does NOT execute the CALL at 00408BA2 the "nag" screen will never display.

From these two facts flow the obvious conclusion that if the CALL at 00408B80 returns EAX as anything but zero, then the program will be cracked. Setting the system date forward to expire the program and setting a breakpoint on 00408B8A and 'forcing the jump' through manual clearing of the zero flag while under SoftIce confirms that this is indeed the crack. When I first attacked this program I thought to myself 'Hmm, that was rather disappointing ... only five minutes to crack the program.'

However, when I made the actual byte change in the diskfile FAXMNG32.EXE, it produced page faults. I immediately assumed I had mistyped the patch (which was nothing more than making the conditional jump unconditional). However, under SoftICE the patch was exactly as it should be - and there was no theoretical reason that this patch should create page faults unintentionally, therefore the page faults must be on purpose (and I couldn't have been more pleased). The first step, of course, was to set a debug register breakpoint for memory reads on the one-byte patch to see if the integrity routine was checking memory. It wasn't, so the only other possibility was that it was checking the file from the disk. Setting a breakpoint on CreateFileA and reviewing the names of the files that were to be opened confirmed that the program was indeed checking itself on disk - and not just once, it was running a thread in the background that was constantly checking the integrity of the file. How nice. Simply renaming the file and keeping a copy of the original file intact was not the solution since the program was bright enough to actually open and check the file under the name that it was executing as well as the correct name of FAXMNG32.EXE.

It is at this point that we address the issue for which this essay is really named: Defeating File Integrity Checks Through Redirection. The first step in the process is determining the location of the CALL that is opening FAXMNG32.EXE for checking.

Setting a breakpoint on CreateFileA as detailed above finds the call in jiffy-quick time. Here is the disassembly of the call that repeatedly opens FAXMNG32.EXE and which we will 'cut out' below:



      :00421B72 55                    PUSH     EBP 
      :00421B73 51                    PUSH     ECX 
      :00421B74 53                    PUSH     EBX 
      :00421B75 52                    PUSH     EDX 
      :00421B76 50                    PUSH     EAX 
      :00421B77 FF1568D04200          CALL     [KERNEL32!CreateFileA] 
      :00421B7D 8BF8                  MOV      EDI,EAX 
    
The next step is to find an area of code that is suitable to hold our 'stealth' routine that will substitute an 'unhacked' copy of the file for the cracked copy. If we look back to where we know we must insert the crack we see the CALL 004221D0 at offset 00408B80, which we know is the key to defeating the date check. If this code routine is not called elsewhere in the program, we can use that code area to house our routine and have that CALL return EAX as nonzero (which is the CRACK!). Setting a breakpoint on 004221D0 confirms that the routine is only used to check the date, thus we now have room to work. First, we apply the crack so that the CALL at offset 00408B80 always returns EAX as non- zero. Putting the value of one in AL and RETurning will do nicely. Thus we now have the following short crack code at offset 004221D0:


      :004221DO BOO1                  MOV      AL,01 
      :004221D2 C3                    RET 
    
Now we must create the routine, right after the short crack code, that will check the name of the file that is to be opened and, if it is the target file FAXMNG32.EXE, change the name to be opened to a file that is identical but unhacked ("virgin"). If it is not the target file, simply open whatever file is named and chain back to the correct code. If it is the target file, open the 'virgin' file that is identical to the original unhacked FAXMNG32.EXE, and then chain back to the correct code. For the "virgin" file I chose to name it !AXMNG32.EXE because of the simplicity of changing one letter in the name. Here is a disassembly of the code that


1) Scans the address on the stack for zero, indicating the end of the filepath name

2) Checks the name of the file, and if it is the target file, replace the first letter of the name with an "!", which is the name of the virgin file

3) Open the file (whether the name was changed or not) and JMP back to the correct code.



      :004221D3 5B                    POP      EBX 
      :004221D4 53                    PUSH     EBX 
      :004221D5 8A03                  MOV      AL,[EBX] 
      :004221D7 43                    INC      EBX 
      :004221D8 OACO                  OR       AL,AL 
      :004221DA 75F9                  JNZ      004221D5 
      :004221DC 83EBOD                SUB      EBX,OD 
      :004221DF 813B4641584D          CMP      DWORD PTR [EBX],4D584146 
      :004221E5 7515                  JNZ      004221FC 
      :004221E7 817B044E473332        CMP      DWORD PTR [EBX+04],3233474E 
      :004221EE 750C                  JNZ      004221FC 
      :004221FO 817B082E455845        CMP      DWORD PTR [EBX+08],4558452E 
      :004221F7 7503                  JNZ      004221FC 
      :004221F9 C60321                MOV      BYTE PTR [EBX],21 
      :004221FC FF1568D04200          CALL     [KERNEL32!CreateFileA] 
      :00422202 E976F9FFFF            JMP      00421B7D 
    

The final step is to write the 'cut out' code, which is simply nothing more than replacing the CALL CREATEFILEA with a jmp to our stealth routine. Here is the disassembly of the code that is listed above after the six byte 'cut-out' patch:


      :00421B72 55                    PUSH      EBP 
      :00421B73 51                    PUSH      ECX 
      :00421B74 53                    PUSH      EBX 
      :00421B75 52                    PUSH      EDX 
      :00421B76 50                    PUSH      EAX 
      :00421B77 E957060000            JMP       004221D3 
      :00421B7C 90                    NOP 
      :00421B7D 8BF8                  MOV       EDI,EAX 
    
That's it. The program is now completely cracked. The background thread that continually checks the file integrity is redirected to a virgin copy of the executable each time it is called - which of course allows it to pass any CRC, checksum, or similar algorithm.

As a final note, I will point the reader to http://www.releasesoft.com, who apparently authored the 'integrity checking system' that Symantec used on WinFax. Apparently, the protection system is quite widespread. Pity, really.





The cRACKER's n0tES are divided into 10 main parts:
 00. INDEX
 01. Assembly for Crackers (CoRN2)
 02. SoftICE (Boot Menu, Setup, Commands)
 03. Breakpoints & Win API Details
 04. Jump Instructions
 05. SET Instructions
 06. Tips & Tricks for Cracking
 07. Window Messages For Crackers
 08. Identifying Functions, Arguments, and Variables (Rhayader)
 09. Commerical Protection Systems
        1 Armadillo
        2 C-Dilla SafeDISC
        3 SalesAgent
        4 SecuROM
        5 softSENTRY
        6 TimeLOCK
        7 VBox
 10. Bitmanipulation (Cruehead)
 11. General Cracking Theory
 12. FAQ

 +A. How to contact me
 +B. What's New?



The cRACKER's n0TES are Copyright © 1998-2000 by TORN@DO of ID. All Rights Reserved. Archived and Re-hosted by Werdstaff