| 
SOFTWrapper: wrapping galore 
        An encryptionless wrapper is a protectionless 
protection
 | 
 
 
Programmers
 | 
| 
2-10-98
 | 
by 
HalVar+
 | 
 | 
  | 
Courtesy of Fravia's page of 
reverse engineering 
 | 
   | 
fra_00E5 980213 Halvar+ 1100 PC XX
  | 
Very interesting essay... as HalVar+ writes: "A funny thing about reversing: While you're at it, it all looks 
new and interesting,and after you're done, you're often surprised how 
trivial the actual crack you considered interesting 5 minutes ago is..." it is true, in a sense, 
yet real knowledge is like that: ad astra per aspera. Enjoy this essay: you may learn 
something about code relocation as well reading it...
 | 
 | 
 | 
Feudalism: It's your count that 
votes
 |  | 
| 
Rating
 | 
(x)Beginner (x)Intermediate ( )Advanced ( 
)Expert
 | 
 | 
A little essay on how to execute only the parts of a wrapper we like; 
only 
those which are necessary to run the main program. Plus some ideas on 
how a
"generic" crack for all programs protected with this wrapper could be 
created.
Interesting for newbies, experienced +crackers will hardly find anything 
new.
   
SOFTWrapper -- an easy to bypass wrapper 
   
   
An encryptionless wrapper is like a protectionless protection 
   
   
Written by 
HalVar+
   
A trend you could see for a while (and which still hasn't completely
disappeared) are the so-called "plugin-protections", like RSAGNT32.DLL
and the like. Some of the IMO most stupid ideas ever were the so-called 
"Wrappers" which basically wrap a finished executable with a "protection
envelope". I will crack a very antiquated example of these wrappers to 
demonstrate how to bypass the parts of the wrapper we do not like while 
executing the parts we need to execute. 
SoftICE 3.01
TASM (optional)  
Do an ftp-search on WRAPEVAL.ZIP (175.157 bytes) :-)
No history, no future, no wonder :-)
In recent times we've seen a drastical increase in so called "Plug&Play"
protections which vary greatly in strenght. Some are fairly strong, but 
many
of them (especially the earlier ones) are nothing but junk to take money 
from the already cracker-newbie-battered shareware authors.
 
The probably weakest version of these "P&P"-protections are those which 
do 
not even require the programmer to integrate them into their program 
source, 
but which take an executable and "wrap" it instead.
The target we're examining here is itself an evaluation version, but so 
sadly
crippled and even in it's full version useless. It is not good for 
anything, 
and the readme.txt points out that it was released in 96 and never used. 
No
wonder if you look at what it does, but for a first study it can help 
pull 
some things together.
This wrapper will add a time/date check to an existing file. While I am 
sure 
it would be trivial to crack the time check or the registration routine, 
I am
sick and tired of the same stupid Registry-Keys or RegKey-checks. I want 
to 
completely bypass everything I do not need and as quickly as possible 
transfer
the control back to the wrapped program.
Since this wrapper is attaching it's functions to an existing file which 
are 
then to be executed before the main program is, it acts in certain ways 
like 
a virus. So what do those AV-people do again to figure out how a virus 
works ?
They create tiny bait files to be infected and examine them 
afterwards.
For this purpose I dug my first Win32-ASM-File out. Well, I think 
everybody
has one or two like these lying around, but I'll give you the short 
source
nonetheless :
----------------------------------cut here------------------------------------
; HalVars 1st Win32 Program, a bait file to be wrapped
.386P
Locals
Jumps
.Model Flat, StdCall
Extrn   ExitProcess:PROC
Extrn   MessageBoxA:PROC
.data
title_box1    db   'HalVar`s Bait', 0
Box_textSTART db   ' Now you can choose : :-)',0
Box_textYES   db   'You pushed the YES Button !',0
Box_textNO    db   'You pushed the NO Button !',0
Box_textEXIT  db   'Do you want to repeat the whole crap ??',0
.Code
  Main:
     beginhere:
        xor bx, bx
        mov bx, 0004h
        push bx
        push offset title_box1
        push offset Box_textSTART
        push 0
        call MessageBoxA
        cmp  ax, 6
        je   Yes_Box
        mov   bx, 10h
        push bx
        push OFFSET title_box1
        push OFFSET Box_textNO
        push 0
        call MessageBoxA
        jmp  EndIt
      Yes_Box:
        mov  bx,10h
        push bx
        push OFFSET title_box1
        push OFFSET Box_textYES
        push 0
        call MessageBoxA
      EndIt:
        mov  bx, 0004h
        push bx
        push OFFSET title_box1
        push OFFSET Box_textEXIT
        push 0
        call MessageBoxA
        cmp  ax, 6
        je   beginhere
        push LARGE-1
        call ExitProcess
End Main
---------------------------------cut here-------------------------------------
Quit laughing already ;-) 
The advantage of using a tiny bait file like this is that you know your
code 100%ly, and that you'll definitely recognize anything that is not 
part
of the original program. Lateron, you should test your findings on a 
bigger 
target, but right now, this one is enough. 
 
Allright, the code is self-explanatory. Compile it, then make a copy
of it before you wrap it. Load the unwrapped bait into the SICE-Loader, 
go
through the whole thing once to know what's going on.
Enter some small explanatory strings for the MessageBoxes
created by the wrapper and run the wrapped bait 
file, and you'll be prompted with a MessageBox which asks you something 
like
"Not expired yet. You want to register now?", and YES/NO-buttons.
Now, since we don't want to crack the registration mechanism, click on 
NO, and
there you are: 
Our bait file. Quit it and load it again, this time 
in the SICE
loader.
The loader will go into SICE at the first instruction of your program. 
Funnily enough, the program does not start at 00401000 any more, but at 
00407000
with the following instructions:
:00407000  call 00407005       ; Hey, it's the old trick to find the  
:00407005  pop ebp             ; delta-offset again :-)  
:00407006  mov eax, ebp        
:00407008  sub eax, 00006005   ; eax now contains 00401000, the original
:0040700D  push eax            ; program starting point, while bp contains
:0040700E  sub ebp, 00000005   ; 00407000, the starting point of the wrapper
Well, old tricks never die: The mysterious (?) call is necessary to know 
the
address of the wrappers' variables, the so-called "delta-offset". This 
is a big
name for something so easy: If you write a program which is intended to 
append
itself to another program, it can't reference to it's own variables in 
the 
standard way: 
lea ax, OFFSET title_box1
will not work, since the offset will be compiled to an absolute address. 
Naturally,
these addresses change when the program is appended, so the above 
snippet would have to
look like this in order to work in an appended program (assuming bp 
contains the delta offset):
lea ax, [bp+OFFSET title_box1]
For more questions concerning the delta offset, consult your local virus 
site.
I could hardly believe it: There, at 00401000, the original program 
entry point, 
lay my own program unencoded, not even XORed :-) This truly IS a weak 
wrapper.
When I looked at this, I, full of youthfull enthusiasm and naivity, 
thought
 "This is too easy !" and made the following change:
:0040700D jmp eax  ; JMP to the beginning of the unwrapped program
And rubbing my hands in glee, I was surprised to see my computer 
splatter in slo-mo
and full color, giving me first a few GPFs and then a stack fault.
So I rebooted, got myself a cup of good tea and looked again. I did the 
same change, 
this time not exiting, but tracing into my own program.
And what did I have to see ? 
:00401009  push 00402000 ; Points to the "HalVar's Bait"-String
:0040100E  push 0040200E ; Points to the "Now you can choose"-String
:00401013  push 00000000 
:00401015  call 0040107A ; But hey, isn't this supposed to be [MessageBoxA] 
                         ; instead ?
The fact that the call references to an address instead of the function 
it
is supposed to call to tells us that the imports haven't yet been loaded 
for
this particular program. So I we'll have to step to our program a bit 
longer 
before we can jump back to our own code. 
So we fire our program up another time and step through the code until 
we 
reach a thoroughly interesting code snippet at 
:00407076  add dword ptr [esi+02], eax  ; eax contains 00400000
:00407079  add esi, 00000006            ; si points to a jumptable
:0040707C  loop 00407076                ; which starts at 00407A0D
The above snippet adds eax to the jumptable's locations, thus 
"importing" the 
most basic funtions which will lateron allow the wrapper
to import further API-calls or dlls.
After it is finished, the jumptable looks like this:
:00407A0D  jmp dword ptr [Kernel32!GetSystemTime]
:00407A13  jmp dword ptr [Kernel32!LoadLibraryA]
:00407A19  jmp dword ptr [Kernel32!GetProcAddress]
:00407A1F  jmp dword ptr [Kernel32!FreeLibrary]
:00407A25  jmp dword ptr [Kernel32!ExitProcess]
:00407A2B  jmp dword ptr [Kernel32!GetModuleFileNameA]
:00407A31  jmp dword ptr [Kernel32!GetModuleFileHandleA]
:00407A37  jmp dword ptr [Kernel32!GetVolumeInformation]
:00407A3D  jmp dword ptr [Kernel32!CreateFileA]
:00407A43  jmp dword ptr [Kernel32!WriteFile]
:00407A49  jmp dword ptr [Kernel32!CloseHandle]
:00407A4F  jmp dword ptr [Kernel32!WinExec]
Well, this does look like a smorgasboard to everyone who wants to import 
more functions, 
but it does little more. None of these table entries include 
[MessageBoxA], which
means that the imports the bait files need are located elsewhere. 
When we trace into the next instruction, we encounter a call to a 
function located
at 00407083; and there it is, finally : The importation of all functions 
needed by
our BaitFile, as well as the usual crap the protection imports to check 
for expirations etc...
Now, for stability's sake, these functions should better be unloaded 
before our
original program is run, therefore we bpx on 00407A1F. We end up (after 
'p ret'ing our way back to our 
code) in the function which unloads all unneeded functions, located at 
004079CE.
Finally, we got everything together to crack this crud.
We change the code to the following: 
:0040707e  call  00407889 ; Import all functions
:00407083  call  004079CE ; Unload all unneeded functions
:00407083  pop   eax
:00407083  jmp   eax
Voila, the crack is done.
A generic crack could be prepared easily for this, just search for the 
bytesequence
"E8000000005D8BC5" (which is the beginning of the wrapped part). From 
there on
you can calculate the offset for the bytes to patch. You would have to 
change the call, though
to something that respects the delta offset, the address to call would 
be (bp+09ce).
This whole protection is incredibly easy to bypass, since it doesn't 
encrypt the 
wrapped program in any way. But one of the nice things about 
programmers: They tend
to put things like en/decryption into nice functions, much like the 
function we 
called at 004079CE.
If there had been an decryption, you could've usually called it in a 
similar way
we unloaded all unneeded functions.
This is in fact a pretty powerful way to bypass big parts of a 
protection: Figure 
out what the functions are doing and call only the parts you're actually 
using.
This does not hold true for any strong wrappers which decrypt only if 
the right 
serial is entered, but as long as the wrapper leaves you time to 
evaluate it, cracking
should be a rather trivial task.
HalVar, February 1998
Well, apparently the programmers of this small prog read a few basic virus 
tutorials and had a few ideas, but while they were at reading these tutes
they could've dug out a few clever ways how to conceal what they're doing
and how to avoid being debugged like this. 
The one thing I learned (and give as advice to every beginner): Get 
yourself a few virus tutorials and learn how to program some DOS-Assembly, 
then learn how to program some simple Win32-Stuff in Assembler. 
This helped me a lot, and without it I wouldn't have written this 
textfile :-) 
I'd like to thank/greet the following people: 
Kneefalls go to: Mammon, Quine, Stone, NatzGul, Fravia, ORC, Razzia, 
                 DataPimp, Yoshi, the whole UCF as well as PhrozenCrew
                 and Revolt...and everyone I forgot
Greets go to: Tin, blorght, bulll, all others in #C4N, Alia, Gnoof, iSa :-)
 
   I wont even bother explaining you 
   that Fravia's ob duh paragraph doesn't apply to this program, since 
   we're just reversing our own program ....
  
You are deep inside Fravia's page of reverse engineering,  
choose your way out:
Back to progcor
homepage
links 
search_forms
+ORC
students' essays
academy database
reality cracking
how to search
javascript wars
tools
anonymity academy 
cocktails
antismut CGI-scripts
mail_Fravia
Is reverse engineering 
legal?