SOFTWrapper: wrapping galore
An encryptionless wrapper is a protectionless
||Courtesy of Fravia's page of
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
(x)Beginner (x)Intermediate ( )Advanced (
A little essay on how to execute only the parts of a wrapper we like;
those which are necessary to run the main program. Plus some ideas on
"generic" crack for all programs protected with this wrapper could be
Interesting for newbies, experienced +crackers will hardly find anything
SOFTWrapper -- an easy to bypass wrapper
An encryptionless wrapper is like a protectionless protection
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.
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
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
not even require the programmer to integrate them into their program
but which take an executable and "wrap" it instead.
The target we're examining here is itself an evaluation version, but so
crippled and even in it's full version useless. It is not good for
and the readme.txt points out that it was released in 96 and never used.
wonder if you look at what it does, but for a first study it can help
some things together.
This wrapper will add a time/date check to an existing file. While I am
it would be trivial to crack the time check or the registration routine,
sick and tired of the same stupid Registry-Keys or RegKey-checks. I want
completely bypass everything I do not need and as quickly as possible
the control back to the wrapped program.
Since this wrapper is attaching it's functions to an existing file which
then to be executed before the main program is, it acts in certain ways
a virus. So what do those AV-people do again to figure out how a virus
They create tiny bait files to be infected and examine them
For this purpose I dug my first Win32-ASM-File out. Well, I think
has one or two like these lying around, but I'll give you the short
; HalVars 1st Win32 Program, a bait file to be wrapped
.Model Flat, StdCall
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
xor bx, bx
mov bx, 0004h
push offset title_box1
push offset Box_textSTART
cmp ax, 6
mov bx, 10h
push OFFSET title_box1
push OFFSET Box_textNO
push OFFSET title_box1
push OFFSET Box_textYES
mov bx, 0004h
push OFFSET title_box1
push OFFSET Box_textEXIT
cmp ax, 6
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
of the original program. Lateron, you should test your findings on a
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,
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
"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
there you are:
Our bait file. Quit it and load it again, this time
in the SICE
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
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
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
itself to another program, it can't reference to it's own variables in
lea ax, OFFSET title_box1
will not work, since the offset will be compiled to an absolute address.
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
I could hardly believe it: There, at 00401000, the original program
lay my own program unencoded, not even XORed :-) This truly IS a weak
When I looked at this, I, full of youthfull enthusiasm and naivity,
"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
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
is supposed to call to tells us that the imports haven't yet been loaded
this particular program. So I we'll have to step to our program a bit
before we can jump back to our own code.
So we fire our program up another time and step through the code until
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
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
but it does little more. None of these table entries include
means that the imports the bait files need are located elsewhere.
When we trace into the next instruction, we encounter a call to a
at 00407083; and there it is, finally : The importation of all functions
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
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
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
"E8000000005D8BC5" (which is the beginning of the wrapped part). From
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
This whole protection is incredibly easy to bypass, since it doesn't
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
called at 004079CE.
If there had been an decryption, you could've usually called it in a
we unloaded all unneeded functions.
This is in fact a pretty powerful way to bypass big parts of a
out what the functions are doing and call only the parts you're actually
This does not hold true for any strong wrappers which decrypt only if
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
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
how to search
Is reverse engineering