SoftWrap v1.x (2findmp3 v5.0)
[Reversing essay]

Subject: Cracking
Target: SoftWrap
URL: http://www.softwrap.com (the wrapper) - http://www.npssoftware.com/2findmp3/retail/2findmp3v50Retailsetup.exe (the software we'll crack wrapped with it)
Author: BlackB
Publisher : +Tsehp on feb 2001
Date: 2001-02-18
Tools used: SoftICE, IDA Pro, Procdump, RegMon, FileMon
Difficulty (scale 1-5): 2 à 3

Before starting!
This essay is for knowledge purposes only!!
Software developers spend much time in making their programs. They live from the money we give them!
Please buy good software!!
I. Introduction

Another commercial wrapper. A pretty bad one.....but let's read first what 's on the official site and what other people write about it.....:

  • "Softwrap™ is the world’s first complete solution for software authors and distributors who wish to securely DISTRIBUTE and SELL their software over the web. It is the virtual answer to Shrinkwrap!Softwrap™ protects your product from piracy, allows you to offer free trials and automates the registration, sale and billing of your software over the net."
  • "No matter what software authors do to distribute their programs, encourage users to pay for their products, and thwart piracy of their software, no single solution has existed to help developers get paid for their efforts. Softwrap's Wrapper just may be that solution - a way for software developers to wrap, market, and distribute their programs digitally and securely.. Yes, Softwrap charges fees for software registrations sales originating from "wrapped" software, but, in this world of free trial versions that often continue being free, instead of being paid for, do you really have anything to lose?" Kerry R. Krueger, Sr. Producer, CMP File Mine
  • "Best ESD solution I've seen." Fred Mitchell, VP Ventrue Development, Adobe
  • "The highly effective and secure Softwrap Wrapper makes it easy for any author to electronically distribute any 32-bit software application. The Free Softwrap Wrapper encrypts .exe files in minutes and allows the author to provide a trial period before the user will be prompted to make a purchase if they wish to continue to use the software beyond the trial period. Additional Wrapper security features include checking for system clock rollbacks, built-in hack detection and the prevention of wrapping already wrapped files." Press Release 11 august 2000

Well, here's the essay that will prove the contrary to what's claimed above....

II. About the protection

The concept:

  1. Wrapper encrypts some important instructions of the original program and renames it to programname.locked.exe
  2. The wrapper makes a loader for programname.locked.exe. This loader has a lot of anti-cracking code.
  3. The wrapper makes a license file named programname.sw + stores copies of the license on several places in the registery

The wrapper/loader allows to buy the program directly via secure online ordering with your creditcard. Of course, a percentage of the money goes to the SoftWrap company.

III. Cracking it

I did quite some research concerning this protection: I tried to unlock the program by entering a serial, tried to crack the loader, tried to unwrap, tried to make SoftWrap believe I just bought the program so it would unlock.

Well, two attempts were successful: the cracking of the loader and the unwrapping. Let's start with cracking the loader :-)

Part 1: Cracking the loader.
***********************

First important thing to tell about the loader is that all loaders for any program are the same! That means that if you cracked one, you can write a patcher to patch ALL of them :-) I found out by downloading SoftWrap and wrapping Notepad. The instructions and locations were exactly the same. So, in this example I used 2findmp3, but you can use any program protected with it.

First thing you'll notice is the anti-softice. It's the typical "check-if-softice-files-are-there" method with the CreateFileA API. So, by setting a breakpoint on this API, you can find following code (it's pretty long, explanations are added in blue):

Start partial code

0041573B _WinMain@16     proc near               ; CODE XREF: start+C9p
0041573B
0041573B arg_0 = dword ptr 4
0041573B
0041573B call sub_409FCD <- Checks operating system to determine SICE/ NTSICE
00415740 cmp byte_42B67C, 1
00415747 mov eax, offset a_Ntice ; "\\\\.\\NTICE"
0041574C jz short loc_415753
0041574E mov eax, offset a_Sice ; "\\\\.\\SICE"
00415753
00415753 loc_415753: ; CODE XREF: _WinMain@16+11j
00415753 push ebx
00415754 push ebp
00415755 push esi
00415756 xor ebp, ebp
00415758 mov esi, ds:CreateFileA
0041575E push edi
0041575F mov ebx, 80h
00415764 push ebp
00415765 push ebx
00415766 push 3
00415768 push ebp
00415769 mov edi, 0C0000000h
0041576E push 3
00415770 push edi
00415771 push eax
00415772 call esi ; CreateFileA
00415774 cmp eax, 0FFFFFFFFh
00415777 mov dword_42B9BC, eax
0041577C jnz short loc_415789 <- If Softice file does not exist, don't jump
0041577E call ds:GetLastError <- Get the error, result in eax
00415784 cmp eax, 5
00415787 jnz short loc_4157A0
00415789
00415789 loc_415789: ; CODE XREF: _WinMain@16+41j
00415789 push dword_42B9BC
0041578F call ds:CloseHandle
00415795 push offset aSoftwrapCannot ; "Softwrap cannot be run with SoftIce loa"...
0041579A call sub_409964
0041579F pop ecx

....some code skipped.... 00415818 loc_415818: ; CODE XREF: _WinMain@16+D6j
00415818 push ebp
00415819 push ebx
0041581A push 3
0041581C push ebp
0041581D push 3
0041581F push edi
00415820 push eax
00415821 call esi ; CreateFileA <- Same story as above
00415823 cmp eax, 0FFFFFFFFh
00415826 mov dword_42B9BC, eax
0041582B jnz short loc_415838
0041582D call ds:GetLastError
00415833 cmp eax, 5
00415836 jnz short loc_41584F
00415838
00415838 loc_415838: ; CODE XREF: _WinMain@16+F0j
00415838 push dword_42B9BC
0041583E call ds:CloseHandle
00415844 push offset aSoftwrapCannot ; "Softwrap cannot be run with SoftIce loa"...
00415849 call sub_409964
0041584E pop ecx
0041584F
0041584F loc_41584F: ; CODE XREF: _WinMain@16+FBj
0041584F push ebp
00415850 push ebp
00415851 push ebp
00415852 push ebp
00415853 push offset aErrorIn ; "Error in"
00415858 push offset dword_42C988
0041585D call sub_4099AE
00415862 add esp, 18h
00415865 push ebp
00415866 push ebx
00415867 push 3
00415869 push ebp
0041586A push 3
0041586C push edi
0041586D push offset a_Regmon ; "\\\\.\\REGMON" <- Hey cool! This prog checks regmon too ;)
00415872 call esi ; CreateFileA <- Same story as with the SoftICE check :)
00415874 cmp eax, 0FFFFFFFFh
00415877 mov dword_42C020, eax
0041587C jnz short loc_415889
0041587E call ds:GetLastError
00415884 cmp eax, 5
00415887 jnz short loc_4158A0
00415889
00415889 loc_415889: ; CODE XREF: _WinMain@16+141j
00415889 push dword_42C020
0041588F call ds:CloseHandle
00415895 push offset aSoftwrapCann_0 ; "Softwrap cannot be run with RegMon load"...
0041589A call sub_409964
0041589F pop ecx
004158A0
004158A0 loc_4158A0: ; CODE XREF: _WinMain@16+14Cj
004158A0 push ebp
004158A1 push ebx
004158A2 push 3
004158A4 push ebp
004158A5 push 3
004158A7 push edi
004158A8 push dword_42C9B8
004158AE call esi ; CreateFileA <- Again the same....
004158B0 cmp eax, 0FFFFFFFFh
004158B3 mov dword_42C020, eax
004158B8 jnz short loc_4158C5
004158BA call ds:GetLastError
004158C0 cmp eax, 5
004158C3 jnz short loc_4158DC
004158C5
004158C5 loc_4158C5: ; CODE XREF: _WinMain@16+17Dj
004158C5 push dword_42C020
004158CB call ds:CloseHandle
004158D1 push offset aSoftwrapCann_0 ; "Softwrap cannot be run with RegMon load"...
004158D6 call sub_409964
004158DB pop ecx
004158DC
004158DC loc_4158DC: ; CODE XREF: _WinMain@16+188j
004158DC push ebp
004158DD push ebx
004158DE push 3
004158E0 push ebp
004158E1 push 3
004158E3 push edi
004158E4 push dword_42C9BC
004158EA call esi ; CreateFileA <- Filemoncheck too, hehe
004158EC pop edi
004158ED pop esi
004158EE pop ebp
004158EF cmp eax, 0FFFFFFFFh
004158F2 mov dword_42B900, eax
004158F7 pop ebx
004158F8 jnz short loc_415905
004158FA call ds:GetLastError
00415900 cmp eax, 5
00415903 jnz short loc_41591C
00415905
00415905 loc_415905: ; CODE XREF: _WinMain@16+1BDj
00415905 push dword_42B900
0041590B call ds:CloseHandle
00415911 push offset aSoftwrapCann_1 ; "Softwrap cannot be run with FileMon loa"...
00415916 call sub_409964
0041591B pop ecx
0041591C
0041591C loc_41591C: ; CODE XREF: _WinMain@16+1C8j
0041591C push [esp+arg_0]
00415920 call sub_415648
00415925 pop ecx
00415926 call sub_410F8E
0041592B call sub_411138
00415930 xor eax, eax
00415932 retn 10h
00415932 _WinMain@16 endp

End partial code

That was pretty clear I think. Just change those JNZ 's to JMP's and it's wasted. Or you can just use FrogSice.
The RegMon and FileMon checks didn't succeed on my system: I was able to run them without any problem. I also noticed that also the registery is checked for SoftICE and RegMon and Filemon. If those last two are found, their .vxd's become temporarely disabled. Well, I'll just show you what RegMon showed me

(RegMon Output):
HKLM\System\CurrentControlSet\Control\SessionManager\KnownVxDs (1.)
HKLM\Software\Softwrap\C8805C2733F945920BE5D4B6B3E1A0851FD4E214 (2.)
HKCR\smallfont\shell\open (3.)

(1.) This checks for RegMon / FileMon VxD's. You can bypass this by moving the directories where they're installd without putting a link to them.
(2.) There's the license
(3.) There's another license, pretty stealthy. Has nothing to do with a "smallfont" or something.

Before trying to crack the time-limit, usage limit, or anything else, let's take a look to the anti-crack mechanism. To do this, just tamper with a .sw file, or temper with the license in the registery. When you run the loader again, you'll get the message that you attempted to crack it. It will recreate the license.
Bad boys as we are, we tamper again. Run the loader again and SoftWrap will tell you that you tried a second hacking attempt and that you can't use the software no more. A message "Two hack attempts have been detected. Unfortunately this program blablabla....The surgeon general says hacking is bad for you :)"
Well, I have another surgeon general who says that hacking is very good for my health, and I rather believe mine then SoftWrap's one :-P

Start partial code

0040AF67 loc_40AF67: ; CODE XREF: sub_40ADC3+14Cj
0040AF67 cmp byte_42BF29, 0 <- First check
0040AF6E jz short loc_40AFB6 <- Jump if no hacking attempts detected
0040AF70 mov eax, [ebp+arg_4]
0040AF73 and dword_42C934, 0
0040AF7A and byte ptr [eax], 0
0040AF7D cmp byte_42BF28, 0
0040AF84 jz short loc_40AF9B
0040AF86 push 1
0040AF88 push edi
0040AF89 push offset aTwoHackAttempt ; "Two hack attempts have been detected. U".

End partial code

Just changing the JZ into a JMP is not enough. You have to put the right value into the memory location, because it gets checked a lot of times more. You should change it like this:

mov byte_42BF29, 0
jmp short loc_40AFB6

There still is another check.....so let's go to loc_40AFB6 (the location our JZ jumps to if we didn't tried to crack the loader)

Start partial code

0040AFB6 loc_40AFB6:                             ; CODE XREF: sub_40ADC3+1ABj
0040AFB6 movsx eax, byte_42BEE3
0040AFBD sub eax, 42h
0040AFC0 jz loc_40B37E <- jumps if there's no time trial or trial usages
0040AFC6 dec eax
0040AFC7 jz loc_40B16B <- jumps if there's a time trial
0040AFCD dec eax
0040AFCE jz loc_40B074 <- jumps if there's a usage trial
0040AFD4 sub eax, 0Ah
0040AFD7 jz short loc_40B014 <- jumps if there are no limitations (that's what we want)
0040AFD9 sub eax, 7
0040AFDC jnz loc_40B394 <- "if none of the above jumps jumped, they cracked me!"
0040AFE2 push [ebp+arg_4]
0040AFE5 mov eax, dword_42BF18
0040AFEA sub eax, dword_42BF14
0040AFF0 push offset off_423584
0040AFF5 push edi
0040AFF6 push eax
0040AFF7 call sub_40A48C
0040AFFC mov eax, dword_42BF18
0040B001 add esp, 10h
0040B004 mov [ebp+var_4], eax
0040B007 mov eax, dword_42BF14
0040B00C mov [ebp+var_8], eax
0040B00F jmp loc_40B394 <- "if they disabled the "they cracked me jump" i can still jump :P"

End partial code

If you're wondering how I found out about those jumps: just disassemble the loader .exe and follow the jumps, you'll notice string references. You can always set a breakpoint on those jumps in SoftICE and make the jump and look what you'll end up with.

Now, remember when I said that it's not enough to change the jumps, but that you also have to adapt the memory locations? Same here! This is how I changed it:

Start partial code

0040AFB6 loc_40AFB6:                             ; CODE XREF: sub_40ADC3+1ABj
0040AFB6 mov byte_42BEE3, 42h <- Putting the right value into the memlocation
0040AFBD mov eax, 42h
0040AFC2 nop
0040AFC3 nop
0040AFC4 nop
0040AFC5 nop
0040AFC6 dec eax
0040AFC7 jz loc_40B16B
0040AFCD dec eax
0040AFCE jz loc_40B074
0040AFD4 xor eax, eax
0040AFD6 nop
0040AFD7 jz short loc_40B014 <- When we're here eax is zero and our jump will jump

End partial code

When you made all the changes in Hiew (or any other hex editor you prefer), fire it up, and see that you can use it as long as you like it. And yes I know, there's still a nag left. I think it's up to you to remove it. To do you a favor I'll give you the location where the nag is created: 40A25E . No thanks ;-P

Again, making a patcher for this loader only is enough to crack all loaders. I tested this with a self-wrapped Notepad ;-)

Part2: Unwrapping
****************

This will be a very short part. Well, it costed me some time to find out, but to explain it's extremely easy. In short, the loader works this way: perform anti-cracking / trial checks, if okay then decrypt vital code, create a new process (to run the locked.exe), write the decrypted code to the process, write garbage to memory to prevent dumping, run the process, exit the loader.

About most of this is executed in this part of code (just set a breakpoint on CreateProcessA to get this location). The trick is to dump the whole stuff before it gets messed-up.

Start partial code

0040C3F2 loc_40C3F2:                             ; CODE XREF: sub_40C0B5+330j
0040C3F2 lea eax, [ebp+var_84]
0040C3F8 push eax
0040C3F9 lea eax, [ebp+var_74]
0040C3FC push eax
0040C3FD push ebx
0040C3FE push ebx
0040C3FF push 4
0040C401 push ebx
0040C402 push ebx
0040C403 push ebx
0040C404 push edi
0040C405 push ebx
0040C406 call ds:CreateProcessA <- Startup locked.exe file
0040C40C test eax, eax
0040C40E jnz short loc_40C43C
....some code skipped... 0040C455 lea eax, [ebp+var_28]
0040C458 push eax
0040C459 lea eax, [ebp+var_60C]
0040C45F push [ebp+var_20C]
0040C465 push eax
0040C466 push [ebp+var_208]
0040C46C push [ebp+var_84]
0040C472 call ds:WriteProcessMemory <- Write decrypted code to locked.exe in memory
0040C478 test eax, eax
0040C47A jnz short loc_40C48F
0040C47C call ds:GetLastError
0040C482 push eax
0040C483 push offset aCanTWriteToExt ; "Can't write to external process memory "...
0040C488 call sub_409964
0040C48D pop ecx
0040C48E pop ecx
0040C48F
0040C48F loc_40C48F: ; CODE XREF: sub_40C0B5+3C5j
0040C48F push esi
0040C490 push ebx
0040C491 push [ebp+var_C]
0040C494 call _memset
0040C499 push [ebp+var_C]
0040C49C call _free
0040C4A1 inc dword_42BF14
0040C4A7 push offset unk_42BEF4
0040C4AC call sub_40CC9A
0040C4B1 add esp, 14h
0040C4B4 call sub_40FA59
0040C4B9 push dword_42C930
0040C4BF call ds:CloseHandle
0040C4C5 push [ebp+var_80]
0040C4C8 mov dword_42C930, ebx
0040C4CE call ds:ResumeThread <- Execute until here, but DO NOT EXECUTE THIS INSTRUCTION!
0040C4D4 pop edi
0040C4D5 mov byte_42C9E5, 1
0040C4DC pop esi

End partial code

When you are on the call ResumeThread, make the program freeze so you can leave SoftICE and can dump the FULL process with Procdump. How to do this?
1. type 'a eip' (enter). This means: assemble a instruction at location EIP (note that eip contains the offset of execution i.e. the point you are at the moment of execution)
2. type 'jmp eip' (enter) This will insert a jump that will jump to itself, making an infinite loop ;-)
3. leave SoftICE and dump the whole process with Procdump
4. when done, get back into SoftICE and clear the infinite jump (again with 'a eip' and putting some NOP's until the call ResumeThread is gone, and you can see the three next instructions. if you don't do this properly, your machine may hang, or the loader may exit with an error)

Now run your dumped file and it should work! Protection wasted ;-)
Last thing to do is to remove the SoftWrap icon from the dumped file. How? With ExeScope (get it at http://protools.cjb.net). First export the original icon from the launcher .exe with ExeScope, then open your dumped file with ExeScope and import the icon you just exported. Save the changes on exit. Job done!

IV. In the end

Another commercial protection wasted. It's certainly not as good as SoftWrap and others claim it to be. However, it's a cheap and easy solution for amateur software authors, but then again, it's a waste because they have to give in a certain amount of money everytime their software get bought, and.....now that SoftWrap is cracked, there is no other way for them to get their money. Sad but true...... . Therefore, if you notice good software wrapped with this lame wrapper, buy it if you use it and send the software author this essay.

To end I'd like to greet and thank +Tsehp for his great messageboard and his great tool ReVirgin. Additional thanks go to all people who help other people out on the messageboard and to all the people who spread this information for free! You guys are the best!

greets

The Blackbird

Endnote:
Essay written by The Blackbird © 1999-2000
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made.