Sunteți pe pagina 1din 17

The Winlicense tutorials v1.

2
by quosego/snd
28-03-2009
Teddy suggested I put all my small tuts in one big paper, so this document holds all the
tutorials Ive made about Winlicense/Themida. Itll be updated when needed, so make
sure you got the latest version.
Some of the topics discussed in this paper may get outdated quickly other things may only
get slightly changed, if you get stuck its always best to just tinker along, reversing is only
the result of a few idiots that tinkered along.

quosego

Contents
The Winlicense tutorials v1.2............................................................................1
Patching the Winlicense 2.0.5.0 - 2.0.7.0 Checksum................................................3
Intro;...................................................................................................3
The checking;.........................................................................................3
Analysis;...............................................................................................3
Patching the checksum 1.x until 2.0.5.0;........................................................4
Patching the checksum 2.0.5.0 until 2.0.6.5;...................................................4
Patching the checksum 2.0.7.0....................................................................5
Finding the Winlicense Is_Registered dwords and patching them in Winlicense
2.0.6.5-2.0.7.0 (and lower)..............................................................................6
Intro;...................................................................................................6
Finding the dwords in 2.0.6.5;.....................................................................6
Finding the dwords in 2.0.7.0;.....................................................................7
Patching the dwords;................................................................................8
Final notes;...........................................................................................9
The REGISTERED macro unraveled in Winlicense 2.0.6.5.........................................10
Intro;..................................................................................................10
Analysis of the Cryptoblock function;...........................................................10
Analysis of the origin of the decryption dwords;..............................................11
Analysis of the origin of the second decryption dword;......................................12
Analysis of the origin of the first decryption dword;.........................................12
Conclusion;..........................................................................................13

Using the is_registered dwords to bypass HWID and banning locks..............................14


Intro;..................................................................................................14
The method of checking antidump by the VM;................................................15
Conclusion;..........................................................................................16
Final Notes;...............................................................................................17

Patching the Winlicense 2.0.5.0 - 2.0.7.0 Checksum.


Intro;
In this tut I'll try to explain how Winlicense checks if the app has been tampered with and
how to patch it.
The checking;
Winlicense his anti patching procedure only holds an simple checksum check, it uses
imagehlp.CheckSumMappedFile to compute this checksum and then compares it to the one
stored by Winlicense and if it isn't the same it fails.
To be exactly it does the following,
-Alloc a memory buffer to store itself from disk.
-Store the PE in this memory buffer.
-Use GetProcaddress to obtain CheckSumMappedFile.
-Use CheckSumMappedFile to compute a checksum.
-Use some logical instructions to modify the checksum.
-Compare the checksum to the one stored at the end of the file.
-If it passes proceed, if it fails give an error.
Analysis;
If you'd breakpoint GetProcaddress and wait for quite some while sooner or later WL will
obtain the CheckSumMappedFile location. If you'd then bp this api and return to WL code
you'll end up somewhere similar to here;
(If the app is using cisc VM, risc VM has a different VM entry.)
0112A5AF
0112A5B4

68 2C31AA09
^ E9 3B7BF9FF

PUSH 9AA312C
JMP 010C20F4

This'll of course leads you to nowhere since it's VM and studying it obfuud is greatly
annoying. However if you look at the stack and scroll up four dwords you'll see the
following;
(these are simply the arguments pushed into CheckSumMappedFile)
(http://msdn.microsoft.com/en-us/library/ms679281(VS.85).aspx)
0007FF6C
0007FF70
0007FF74
0007FF78

012A0000
000B41FC
0112A4D0 cisc_+_f.0112A4D0
0112A4D4 cisc_+_f.0112A4D4

and their meaning;


PIMAGE_NT_HEADERS CheckSumMappedFile(
__in PVOID BaseAddress,
__in DWORD FileLength,
__out PDWORD HeaderSum,
__out PDWORD CheckSum
);
The checksum is the most important (located at 0112A4D4). If you'd check out that dword
you'll find the checksum. You can, if you've patched WL, feed it here the correct

checksum. But that would include hooking the WL decrypting routines or GetProcAddress
or similar. There are easier methods.
WL does not directly compare the CheckSumMappedFile generated checksum with a
checksum it has stored, instead it does some computations before comparing the
checksum.
In my case it did the following computations, extracted from the Cisc Virtual Machine.
ROL {checksum}, {last byte checksum}
;ROL 000B6D92,92
XOR B648002D,2AC8914C
ADD 9C809161,87C05B78
XOR 2440ECD9,6D10B8E2

=
=
=
=

B648002D
9C809161
2440ECD9
4950543B

In this case 4950543B is considered the final calculated checksum. If you now set a memory
breakpoint on access on the BaseAddress of the mapped PE (see the CheckSumMappedFile
structure) in the memory map. You'll see the VM accessing the very last dword in the
mapped file. This will if the executable is unmodified be the same as the calculated
checksum. WL will next do a compare and fail or proceed.
Patching the checksum 1.x until 2.0.5.0;
So if you've modified your WL protected app you must update the checksum located in a
dword at the end of the file, however as I stated all calculations of this checksum are done
within the VM and it would be tedious to extract them every time.
However WL stores the calculated checksum in the VM registers before comparing it with
the stored one. So to find it easily you can do the following;
- When you've returned from CheckSumMappedFile API memory bp the BaseAddress on
access in the memory map. Press shift-f9. (It now has obtained the last dword of the
mapped PE.)
- Follow edi in dump and look for the first dword that appears two times, this is the
calculated checksum. In cisc VM's it should be [edi+4] and [edi+8], in risc VM's it should be
further down with some empty dwords between it.
- Copy the calculated checksum to the end of the file (search for the old one or just scroll
down). It'll now run again with its new checksum.
Patching the checksum 2.0.5.0 until 2.0.6.5;
There's not much they've updated, except it gets the CheckSumMappedFile API through the
internal kernel32.dll GetProcAddress of Winlicense. So here's another method, though you
can also bp the internal Getprocaddress and proceed with the above tutorial the following
might be easier.
- HW bp on access the last dword of the file that needs checksum updating and run. (This
is the stored checksum, as you know)
- Wait until it writes it using a rep to a memory buffer.
- Then HW bp the checksum at the memory buffer. (eg. the last dword in the memory
buffer.) Just follow EDI in dump and hw bp that dword. Run and wait until it gets accessed
by the VM.
- Follow edi in dump and look for the first dword that appears two times, this is the
calculated checksum. In cisc VM's it should be easy to spot, in risc VM's it should be further
down with some empty dwords between it.
- Copy the calculated checksum to the end of the file (search for the old one or just scroll
down). It'll now run again with its new checksum.

Patching the checksum 2.0.7.0


Theyve did some updates, not many interesting ones.. Generic idea is still the same,
however one updates makes sure the previous tuts are useless;
-Load the stored checksum prior to the calculations, this means when you hw bp it the new
checksum wont be in [EDI] anymore.
Theyve probably made some other updates but since I didnt notice them they are of no
concern.
But as usual they made a mistake so that once again an easy fix without VM digging is
possible. To update the checksum in 2.0.7.0 follow the following tut.
- bp FreeLibray, run and wait until it breaks, eax and ecx hold the old and calculated
checksum.
- Copy the calculated checksum to the end of the file (search for the old one or just scroll
down). It'll now run again with its new checksum.
Hmm kinda short tutorial.. Was hoping for more, but it seems oreans is not in the mood.
This also works for the previous versions.

Finding the Winlicense Is_Registered dwords and patching them in


Winlicense 2.0.6.5-2.0.7.0 (and lower).
Intro;
Most Winlicense protected apps simply rely on Winlicense to check for registration. They
always do this using the WL API's and occasionally with some custom macro's. You can
easily modify the API to return eax=1 and be done with it, however this usually does not fix
the macro's/other custom checks or Trial checks. You can patch these as well and this is
what I usually did. However it seems Winlicense only has two dwords it checks to see if it's
registered, making sure that these hold the correct dwords registers the entire app with
only a two dword patch.
Update Notes for 2.0.6.5;
Oreans has updated the dwords, and to be honest not as lame as the other updates. This
time I'll have to guide you through the Virtual Machine to obtain the correct is_registered
dwords. Since they're now no longer fixed and available in normal code. But don't worry,
it'll be painless. :)
Update Notes for 2.0.7.0;
Oreans finally has hidden the is_registered dword correctly. They can no longer be found
using the search strings used in the 2.0.6.5 version. All accesses to them are decrypted and
encrypted when executed or VMed. The registered macro now uses a different dword to
check if its registered. And finally the name api does not crash anymore when youve got
the is_registered dwords fixed.
Finding the dwords in 2.0.6.5;
Not much updates here since the older versions, run the app and search for the following
strings in the WL section.
1)
B8 01 00 00 00 89 85 ?? ?? ?? ?? C7 85
Finds the following code;
MOV EAX,1
MOV DWORD PTR SS:[EBP+xxxxxxxx],EAX
MOV DWORD PTR SS:[EBP+xxxxxxxx], {Variable_1)

// Not important
// Not important
// EBP+xxxxxxxx holds the dword

(The EBP+xxxxxxxx in the third line of the found code is the location of the first
is_registered dword)
{Variable_1} is a random value, which WL checks for to see if it's not registered, however
the correct value is not 2 here, but also random. If {Variable_1} equals the stored value
then WL accepts the program as unregistered.
2)
00 00 00 00 00 00 00 00 81 BD
Finds the following code;
CMP DWORD PTR SS:[EBP+xxxxxxxx],{Variable_2)
(EBP+xxxxxxxx is the location of the second is_registered dword)

{Variable_2) is in this case, the value the second is_registered dword needs to be. If the
stored second is_registered dword equals {Variable_2) then WL accepts the program as
registered. (If of course the first dword is also valid.)
Put a hardware breakpoint on execute on the found addresses and restart the app. Next
when you stop on these instructions you can read the memory locations which they
compare to or write to. These are the locations were WL stores the is_registered dwords.
Finding the dwords in 2.0.7.0;
New search strings new chances.
Start your app let it run and search for the following strings in the WL sections;
1)
50 53 B8 89 04 00 00
When found scroll up until you find something similar to this;

The above is a encryption/wiping loop, it overwrites everything above itself. As you


probably can see above this is only bogus junk code that has already been wiped by the
above loop. So HWBP on execute this loop and restart to see the function prior to being
wiped.
However make sure theres not another loop slightly above this loop. If youve restarted
and scrolled up to above the loop youll see the function thats about to get wiped. Now in
this function search for the following;
CMP DWORD PTR SS:[EBP+xxxxxxxx], {Variable_1)

// EBP+xxxxxxxx holds the dword

Here the EBP+xxxxxxxx in this line of the found code is the location of the first
is_registered dword.
{Variable_1} is a random value, which WL checks for to see if it's not registered, however
the correct value is not 2 here, but also random. If {Variable_1} equals the stored value
then WL accepts the program as unregistered.
2)
50 53 8B C0 B8 9F 04 00 00
When found scroll up until you find the following (~10 lines);
SUB ECX,5
REP MOVS BYTE PTR ES:[EDI],BYTE PTR DS:[ESI]
However often olly doesnt analyse the above code correctly so you can also search for the
following byte string; 83 ?? 05 F3 A4. When found, HWBP it on execute and restart. Now
scroll up and youll see another encryption/wiping loop thats about to get wiped by the
rep movs mentioned above. Now HWBP on execute this loop (wipe the previous HWBP) and
restart. Now when you again scroll up youll once again see a function thats about to get
wiped. In this function search for the following;

CMP DWORD PTR SS:[EBP+xxxxxxxx],{Variable_2)


Here EBP+xxxxxxxx is the location of the second is_registered dword.
{Variable_2) is in this case, the value the second is_registered dword needs to be. If the
stored second is_registered dword equals {Variable_2) then WL accepts the program as
registered. (If of course the first dword is also valid.)
So now youve found the locations of the is_registered dwords in version 2.0.7.0 and the
value that the second is_registered dword must be when registered.
Patching the dwords;
In previous versions the correct values of the is_registered dwords were fixed (2 & 500),
however now they're randomly generated and using the information discussed in the
previous paragraph you only know the correct value of the second dword. As for the first
dword you only know the correct dword to make it unregistered. Which pretty much helps
you nothing at all.
I will now explain how you can trace the Oreans virtual machines to get the correct first
is_registered dword. As you might know there are two possible Virtual Machines, Risc and
Cisc. Since they differ in complexity and execution methods, I've made two tuts to find the
first is_registered dword. Use the correct one for the correct VM. A simple rule is if the VM
is located inside the WL section it's cisc, else it's risc.
For version 2.0.6.5;
Winlicense accesses and compares the correct first is_registered dword with the stored one
the second time it accesses it in the VM. So first HW bp on access the location of the first
dword. Then restart and press shift-f9 until you hit the code were it writes the
{Variable_1). (See 1) in Finding the dwords.) Next press f9 and you'll be at the first access
in the VM, next press f9 and you're at the second access. Next it'll compare the stored first
is_registered dword with the correct one. Now you'll have to choose between the cisc or
risc tut.
For version 2.0.7.0;
Winlicense accesses and compares the correct first is_registered dword with the stored one
the third time it accesses it in the VM. So first HW bp on access the location of the first
dword. Then restart and press shift-f9, first time youll break at a rep that writes zeroes
and the second time you end up in the VM. Now press shift_f9 another two times and
youre near the compare to the correct value.
Comparing in cisc Virtual machine;
- Press F7 to arrive at the main lods handler, you can see {Variable_1) in the stack.
- Put a breakpoint here and f9 until you see {Variable_1) in ecx
- eax now holds the correct is_registered dword. Store this at the first is_registered dword
location and your app will be registered. (If you also fix the second of course.)
You'll now prolly think, well that's nice but since I'm in this screwy virtual machine you
better tell me why this actually works. Simple see the unobfuscated handler below which
compares values in the cisc VM;
POP EAX
POP ECX
CMP ECX,EAX
PUSHFD
JMP {Main_Handler)

// All handlers return to the main handler.

Since your {Variable_1) was pushed first it will be in ecx, and eax must hold whatever it is
compared to. Junk VM code never writes stack values to eax or ecx so {Variable_1) can
never get to ecx unless it's intended. (The above handler is unobfuscated, it can take
extremely long if you try to trace and find this handler yourself.)
Comparing in risc Virtual machine;
- Trace until {Variable_1) which is retrieved from its store location is located at second
dword of the stack, should be a pretty short trace 20 instructions max.
00391FF8
00391FFC

7EAC5730
00000000

<-- pushed is_registered dword {Variable_1)


<-- begin of stack

- Hardware bp that stack address on access (here 391ff8), and run. When it breaks the
correct is_registered dword is now located in the dword above the old one in the stack.
Store this dword at the first is_registered dword location and your app will be registered.
(If you also fix the second of course.)
Once again you might ask yourself and why does this work?? And again once you know the
unobfuscated code all becomes clear;
MOV ECX,DWORD PTR DS:[ESI]
MOV EBX,DWORD PTR DS:[ESI-4]
PUSH DWORD PTR DS:[EDI+70]
POPFD
CMP ECX,EBX
PUSHFD

<-- get {Variable_1)


<-- get correct
<-- compare

Well that's all, after you've unpacked the app just set the first and second dwords correctly
and everything will once be registered. Or use an inline to fix these dwords after the app
has been unpacked in memory.
Final notes;
Once again Winlicense can crypt certain blocks of code using dwords written when a
keyfile is present, these will not be decrypted and can crash. Also the Get_name API will
crash! Since there's no name you can put a ret 0c in its place which most apps will accept
or patch it to return a name.

The REGISTERED macro unraveled in Winlicense 2.0.6.5


Intro;
In this part of my series about Winlicense I'll unravel the decryption of certain code parts
that use the REGISTERED_START REGISTERED_END macro. This tut won't be as directly
useful as the previous parts. Since you prolly still need a correct keyfile to fix these blocks,
and after you've unpacked an app with a key it's unnecessary to do anything with these
blocks. But still it'll give you a nice idea what Winlicense does and how it uses the keyfiles.
Cryptoblocks, as I decided to call them, are encrypted pieces of information/code, that
only get decrypted when a valid keyfile/or the required decryption dwords are available,
and the program thinks it's registered. (These blocks also use the is_registered dwords, I've
mentioned in previous tutorials that these blocks can crash if you've fixed the is_registered
dwords.)
Once again this'll include some VM tracing and analysis. Please note, I make use of an
unobfuscated Virtual Machine. Sadly enough the techniques developed by me and others to
unobfuscate VM's are not publicly available, except for the recent release of the Code
Unvirtualizer 0.1 by Deathway which has this implemented. You can use this tool to do
some analysis yourself if you wish to expand on this tutorial. I however have not used this
tool so I don't know its effectiveness. I will however try to make it so that you can even
follow this tut with an obfuscated cisc VM.
Analysis of the Cryptoblock function;
First of all how can you find these CryptoBlocks, this is actually quite easy and very similar
to the finding of CodeEncrypt functions. A simple search for the following binary string will
find you the Cryptoblocks.
E8??????00????00000000000000????2020
This'll lead you to a call to the REGISTERED macro, below I'll explain an example of such a
REGISTERED macro in parts.
PUSHAD
CALL 0064EC8F
POP EBP
SUB EBP,9D41080

//call the line below


//pop call return address into ebp
//substract to get correct ebp value

As often the case with Themida and Winlicense uses EBP to get memory locations.
(eg MOV DWORD PTR SS:[EBP+9D41076],ESI now equals for instance, MOV DWORD PTR SS:
[00551849],ESI)
MOV ESI,DWORD PTR SS:[ESP+20]
called
[2];
CMP DWORD PTR DS:[ESI],20204C57
JNZ [1]
CMP DWORD PTR DS:[ESI+4],3
JE 0064ECB6
[1];
INC ESI

//load the address from which the macro was


//are we at the beginning/end
//are we at the last 20204c57 (end)

JMP [2]
SUB ESI,2
MOV DWORD PTR SS:[EBP+9D41076],ESI
Store the address that marks the end of the encrypted data.
CMP DWORD PTR SS:[EBP+9C11311],70D42925
JNZ [end]
CMP DWORD PTR SS:[EBP+9C1219D],72EF7845
JNZ [end]
JMP 0064ECE9
[...]
Check for the is_registered dwords, also a nice place to see what they are supposed to be.
Though not always available.
MOV EAX,DWORD PTR SS:[EBP+9C10F19]
MOV EBX,DWORD PTR SS:[EBP+9C10FDD]
Get the decryption dwords from the Winlicense data.
MOV ESI,DWORD PTR SS:[ESP+20]
ADD ESI,0D
[3];
CMP ESI,DWORD PTR SS:[EBP+9D41076]
JE [exit]
Load start address of the cryptoblock to decrypt, and compare to the end of the block.
ADD BYTE PTR DS:[ESI],AL
ADD BYTE PTR DS:[ESI],BL
XOR BYTE PTR DS:[ESI],AH
XOR BYTE PTR DS:[ESI],BH
SUB BYTE PTR DS:[ESI],AL
SUB BYTE PTR DS:[ESI],BL
XOR BYTE PTR DS:[ESI],AH
XOR BYTE PTR DS:[ESI],BH
ROR EAX,4
ROR EBX,3
INC ESI
JMP [3]
Decrypt the block using the EAX and EBX dwords a simple decryption routine.
Analysis of the origin of the decryption dwords;
The origin of the decryption dwords as loaded in EBX and EAX is interesting as it could
proof to be an interesting point of attack. Are they simply random numbers preloaded in a
Winlicense protected app or are they actually retrieved from the keyfile. The first would
make the cryptoblocks easily retrievable whilst the keyfile is not available, the second
would make it harder. However I've already spoiled it somewhat for you guys saying that
they are actually retrieved from the keyfile. I'll now discuss how I achieved this.
---

First, something about the VM. It has the following simplified structure, a main handler
interprets bytes and jumps to the accompanying specific handler. This handler executes its
code and the main handler interprets the next byte.
So the main handler gets byte 31, decrypts it and sees that byte 31 means executing
handler number 4 which pushes ebx. It'll jump to the "push ebx/number 4 handler" which
will push ebx and go back to the main handler. Now it'll get the next byte and so on.
--Analysis of the origin of the second decryption dword;
Now HW bp the location of the first decryption dword and restart, this'll get you at least to
the area of code where this decryption dword is written. Skip a few reps that write zeroes
at this location until you get to the virtual machine handler that writes this dword.
POP DWORD PTR DS:[EDX]
JMP {Main_Handler)

// All handlers return to the main handler.

Hw bp the VM register (follow EDI in dump and find the decryption value) that contains the
first decryption dword. Next time it'll be accessed it'll be for the calculation of the second
decryption dword, and it'll have pushed it onto the stack. You can also find this by bping
the main handler and see the dword appearing in the stack. Unless you've deobfuscated
your VM I don't suggest tracing through specific handlers. There are ~30 handlers between
the writing of the first dword and the calculation of the second.
Next you can bp this dword in the stack to see where it gets accessed, (remove the
previous one) once again unless you've got no obfu don't trace since there's a lot of junk
code between normal instructions. (push pops, word loads, 4 adds. etc.) You'll end up in a
handler doing the following;
POP EAX
ADD DWORD PTR SS:[ESP],EAX
PUSHFD
JMP {Main_Handler)
[ESP] holds a fixed value loaded from VM_code and eax holds the first decryption dword. It
should be obvious that they get added to each other here.. Now check out the value in the
stack, indeed it's the second decryption dword.
So you now know the second decryption dword is derived from the first. However that does
not tell us anything about the origin of the first dword. This will be discussed in the next
chapter.
Analysis of the origin of the first decryption dword;
Restart the app and use an hw bp on access on the first decryption dword location to once
again break in the VM were it writes this dword. However right now you're already too
late, the decryption has both been calculated and written.
But as you might have noticed the main handler loads VM_code bytes from ESI which makes
it decide which handler it needs to call, this is the actual code being executed right now in
the VM. So why not scroll back a bit here and put a bp earlier in the VM. So follow ESI in
dump, marvel at the encrypted VM_code scroll up about 13 lines. There's lots of junk in
VM_code so you can scroll up quite some bytes. (Please note that the amount of lines is
guesswork, the amount of junkcode is variable.)

Hw bp this byte on access and restart and f9 until you're in the VM. If you now follow EDI in
dump to see the VM_registers, you must check to see if the first decryption dword is no
longer in the VM registers. If it still is then you've not scrolled up enough lines. The first
VM_register ( simply [EDI] ) holds an interesting value, a memory buffer. A few lines down
in another VM_register there's the first dword located at this memory buffer.
00528645 02660000
[..]
00528651 A3D9D3B7
[EDI+4])

//First VM_register, [EDI]


//dword located at 2660000 (fourth VM_register

Right now I'll just tell you that the 2660000 is the memory buffer holding the keyfile which
went through a few decryptions. Hw bp this address and restart to find out for yourself.
Now hw bp the VM_register containing the first dword of the keyfile memory buffer. (In
the above example the one with A3D9D3B7.) and press f9. When you break it'll have
pushed this value on the stack. Next you can bp this dword in the stack to see where it
gets accessed,(remove the previous one). You'll end up in a handler doing the following;
POP EAX
XOR DWORD PTR SS:[ESP],EAX
PUSHFD
JMP {Main_Handler)
Check the stack and you'll see the first decryption dword.
We now know that the first decryption dword is derived from the first decrypted dword of
the keyfile. The first decryption dword is then used to calculate the second decryption
dword.
Conclusion;
To decrypt certain codeparts in registered Winlicense protected apps Winlicense uses the
first dword of the keyfile to calculate the decryption dwords. These dwords then get used
to decrypt the REGISTERED macro's encrypted code/data.
In pseudocode the following happens to obtain these decryption dwords.
MOV EAX, [FIRST_BYTE_KEYFILE]
XOR EAX, [FIXED_VALUE_85737364]
MOV [WL_DATA_1],EAX
ADD EAX, [FIXED_VALUE_05BE6546]
MOV [WL_DATA_2],EAX
[WL_DATA_1] & [WL_DATA_2] now contain the decryption dwords.

Using the is_registered dwords to bypass HWID and banning locks.


Intro;
As proven by the loaders/scripts that bypass trial and HWID made by LCF_AT the
is_registered dwords are also used to see if licenses are valid in packer code. A logical
result is that changing them to their correct values when incorrect but valid license are
present will result in running programs.
This tut will simply show hoe you can use the is_registered dwords to make programs that
use banned license and wrong HWIDs work once more. These apps however require
unpacking, loaders or inlines to keep working.
Setting the is_registered dwords correct at the right time.
HWID;
This one is quite simple and wont require much explanation. Normally youll get two
message boxes when you try to run a program with a license meant for a different
computer;
1. This application has been registered to xxxx xxxx.
2. The current key has been locked to a different machine.
Simply modifying the is_registered dwords at the first message box to their correct values
will make the program run.
Banned License;
Here youve only got a message box saying that your license has been banned. So well
need to dig somewhat further. Not too much though.
Put an hw bp on write on the second is_registered dword and run. First youll see it zeroed
and then changed to the correct value and then to a different value. Now change it to the
correct value again and the program runs.
Quite simple and whole lot easier than digging VM searching for zeroes and 1 and other
HWID tricks. Trial values etc. can also be fixed using these kinds of tricks.

The Stack Antidump in Winlicense and Themida 2.0.6.5


Intro;
Yes this is it; I will now explain the complete workings of the stack antidump. Though this
is just one antidump, there are many more, it is the one I know best. The other antidumps
will stay a mystery until someone decides to make a tut about these.
The antidumps are checks by the Oreans Virtual Machine to see if it was dumped. If it is
itll check these and if not available the VM will produce an error. The stackantidump in
particular is a check for a qword in the stack. If its not available, the check for it in the
Virtual machine will not pass.
I will not tell you how to defeat it, only what makes it tick. You should be able to defeat it
yourself.
The location of the stackantidump;
Well the name says it all, its located in the stack. As you might have noticed when an
Oreans protected app is at its oep the stack is already filled with some info. Normally in XP
apps start at xxffc4 in the stack (esp), most protectors at the oep start the app at this
same location. However the OEP in Oreans protected apps start at lower values (~xxff38).
This has no effect on apps theyll still just run, theyll only use different stack addresses
than unprotected apps.
Now when you unpack an app the app will once again start at xxffc4 and all those values
Winlicense or Themida put before their oep will not be there, the stack gets wiped when
you restart a program. The VM makes use of this by checking these addresses for their
correct values. When unpacked these values are not there so the VM knows its been
dumped.
To be exact the location of the stackantidump is when you are at the EP of an Oreans
protected app [esp] and [esp-4] usually 12ffc4 and 12ffc0 in XP.
The method of checking antidump by the VM;
The antidump is written using the following code, this was obtained from the VM, the
methods used to do this however stay private.
mov
mov
mov
mov
mov
xor
mov
xor
mov

[data_1], fixed_value_1
ecx, xxffc0
[ecx], fixed_value_1
eax, [ecx]
ebx, [ecx+4]
eax,ebx
[ecx],eax
ecx, fixed_value_2
[data_2],ecx

//Store random value(1)in packer_data.


//Get stackantidump location.
//Store random value(1)@esp_xxffc0
//xor [xxffc0],[xxffc0+4]
//Store result at esp xxffc0
//xor xxffc0 with a random value
//Store in packer_data.

The above stores 2 dwords that the VM will later use to check stackantidump, data_1 and
data_2. Data_1 holds the variable that must be the same when [xxffc0] and [xxffc0+4] are
xorred. Data_2 holds the location xorred with fixed_value_2, the VM will use data_2 to
calculate where the stackantidump is located.
To check stackantidump the VM now only needs to the folowing;
- Retrieve data_1 and data_2.
- Xor data_2 with fixed_value_2 to get the location of the stackantidump.

-Get the dword located at that location.


-Xor this dword with the dword at [location + 4].
-Check if this result equals data_1, if not press selfdestruct.
Conclusion;
To check if the VM is dumped the VM checks certain values in the stack. It then xors these
values and checks if they are the same as a stored value. If they are not the VM will take
action to prevent execution.

Final Notes;
Thank you all for reading this, hope you enjoyed it.
Greetings to all webscene teams, and the reversers visiting the RE boards and thnx to a
certain provider of executables.
You cannot stop a tide with a spoon. Cracking technology will
always be several steps ahead of DRM and content will be
redistributed on anonymous networks. Giulio Prisco, chief
executive of Metafuturing Second Life, formerly of CERN

-q

S-ar putea să vă placă și