reversing of a protection scheme based on drivers v11 by shub-nigurrath
TRANSCRIPT
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
1/38
Sometime happens to fall into an interesting protection which reveals to be
nicely implemented and nice to describe into a tutorial. This time is the turn of
SandBoxie, a program that has an nice protection schema. I thought it could
have been useful to reverse and document in a tutorial, mostly because I used
a lot a combination of OllyDbg and IDA Debugger.
This time I preferred using IDA as much as possible to understand the code and
then OllyDbg only to verify the assumptions done. This method of investigation is
usually very common when you have to analyze malware, but also very handy,
because IDA allows saving of reversing sessions, code editing, name changing
and so on.
I need reversing instruments that could be frozen at any time (I have very few
and scattered spare time): I usually run the dynamic sessions with OllyDbg on a
VMWARE virtual PC which I can freeze at anytime and the analysis sessions with
IDA (which can also be closed and started again later for another session).
I will end this journey doing a complete keygen of the program, showing the
process you can use too with other programs and will include in the distribution
its sources (simple C).
As usual there are cracks and keygens too for this program around the net and
this tutorial will not create many troubles than those already created by
someone else before me.
Moreover it will then be the occasion to deeper dig the IDA functionalities in
combination with OllyDbg, I will try to be as much clear as possible, for
everyone.
Have phun,
Shub
Forewords
Into this Tutorial
1. The target
2. Understanding the protection
structure
3. Understanding the flow ofdata
4. Using Olly and IDA together:
taking advantages from both
5. Analyzing the driver with IDA
6. Preparation of a valid patch
7.
Patching the driver
8.
Keygenning the program
9.
Conclusions
10.
Further Readings/References
Author: Shub-Nigurrath
RReevveerrssiinnggooffaaPPrrootteeccttiioonnSScchheemmee
bbaasseeddoonnddrriivveerrss::SSaannddBBooxxiiee
SS hhuubb -- NN iigg uu rr rr aa tt hh [[ AARRTT EE AA MM ]]
Version 1.1Last Rev.: August 2007
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
2/38
PAGE 2REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Disclaimers
All code included with this tutorial is free to use and modify; we only ask that you mention where you found it. This
tutorial is also free to distribute in its current unaltered form, with all the included supplements.
All the commercial programs used within this document have been used only for the purpose of demonstrating
the theories and methods described. No distribution of patched applications has been done under any media orhost. The applications used were most of the times already been patched, and cracked versions were availablesince a lot of time. ARTeam or the authors of the paper cannot be considered responsible for damages to the
companies holding rights on those programs. The scope of this tutorial as well as any other ARTeam tutorial is of
sharing knowledge and teaching how to patch applications, how to bypass protections and generally speaking
how to improve the RCE art and generally the comprehension of what happens under the hood. We are notreleasing any cracked application. We are what we know..
Verification
ARTeam.esfv can be opened in the ARTeamESFVChecker to verify all files have been released by ARTeam and
are unaltered. The ARTeamESFVChecker can be obtained in the release section of the ARTeam site:http://releases.accessroot.com
Table of Contents
1.
The Target and its limitations ...................................................................................................................................... 3
1.1.
Trial mode limitations .......................................................................................................................................... 4
2.
Understanding the protection structure ................................................................................................................... 5
2.1.
Deeply looking at CheckStatus routine ............................................................................................................ 7
2.2.
Analyzing the dll SbieDll.dll ................................................................................................................................ 8
2.2.1
How the InputBuffer is crafted .................................................................................................................... 12
3. Looking at the driver SbieDrv.sys ............................................................................................................................. 12
3.1. Deeper look at the DispatchRoutine .............................................................................................................. 14
4.
The final work: patching the driver.......................................................................................................................... 18
4.1. Patching the handler of StartProcess ............................................................................................................. 18
4.1.1
A deeper look at the HStartProcess routines ........ ......... ......... ........ ......... ......... ......... ........ ......... ......... ...... 204.2. Patching the handler of SetLicense ............................................................................................................... 21
4.3. Patching the handler of GetLincense ............................................................................................................ 23
4.4. Fixing the header of the driver: checksum of PE Header ............................................................................. 26
5. Keygenning the Program ......................................................................................................................................... 285.1.
Testing the atomicity of the SerialCalculation routine .................................................................................. 29
5.2.
Loading the modified driver into OllyDbg ..................................................................................................... 31
5.3.
Coding the keygenerator ............................................................................................................................... 33
6.
References ................................................................................................................................................................ 38
7.
Greetings ................................................................................................................................................................... 38
This is the tutorial number 200. Wereleased 200 Tutorials!! This is anastonishing result for a team as our, 200original tutorials published on our pages!Hip hip hip hurray to us. Long liveARTEAM!!http://arteam.accessroot.com
http://releases.accessroot.com/http://releases.accessroot.com/http://arteam.accessroot.com/http://arteam.accessroot.com/http://arteam.accessroot.com/http://releases.accessroot.com/ -
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
3/38
PAGE 3 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
1. The Target and its limitations
The target is SandBoxie[1], a program that creates a sandbox for any program running on your system. A sandbox
means a protected execution environment which virtualizes the program inserting a virtual layer between the real
operative system and the application. This layer will take care of the system calls of the application and will divert
them into a safer place, a local database. The target is to have a safer execution place for application without
the load of a complete virtual machine like VMWARE. These environments are indeed really popular becauseoffer a safer execution environment without slowing down too much the application, like the real virtualization PCprograms (e.g. VMWARE or VirtualPC).
Technically speaking these programs divert the kernel level functions used by the system to access files, registry
and memory adding hooks that divert the execution to a local database (where the data come and go). It is thesame technique used by the rootkits (seeFigure 1).
Figure 1 - SandBoxie essentials
Of course the first thing is as usual to install the application and see if and how its components are protected. Youcan find in the installation directory these executables:
Control.exe SbieDll.dll
SbieDrv.sys
Start.exe
There are other executables of course but their names identify them clearly as auxiliary programs, moreover they
do not have any graphic resource inside (no dialog, no strings etc).
For all of them the PEiD reports:
Good, it seems at all a simple target, a target for which a tutorial shouldnt be needed..or not?
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
4/38
PAGE 4REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
1.1.Trial mode limitations
The limitations of the program in unregistered mode are essentially three:
1. 30 day limit of usage
2. Is not possible to run more than one program into different sandboxes
3. No advanced features, like automatic alarms when a program runs out of any sandbox or launching a
program always into a sandbox
Try to follow these steps to verify what I told:
A) Create a second sandbox called secondone and select the DefaultBox
B)
Launch any program into the sandbox, like for example the calc.exeC) The calc.exe if placed into the sandbox will have a different name with # before and after the window
titlebar.
D) The list of processes you can sandbox into a single sandbox is unlimited but try to change the sandbox ..
E) Now select the secondone and try to launch again the calc.exe but this time into this secondsandbox.
F) You get a message like above..
Other limitations are those inFigure 2,andFigure 4. Figure 3 is interesting also because tells us that the alarm thatwill be triggered by the system is of type SBOX1118.
Figure 2 Registration schema and badboy message
A)B)
E) F)
C)
D)
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
5/38
PAGE 5 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 3 automatic warning if a program runs outside the sandbox
Figure 4 about dialog
2. Understanding the protection structure
We know enough of the program in order to start reversing it. We will start from what appears the most logicalpoint: start.exe.
We analyze start.exe using IDA before running it and looking at the start function we can see that the structure is
quite simple: it calls some exports of the SbieDll.dll dll and then an interesting function at 01003A35 (call
sub_1003120). This call contains a lot of interesting messages, among which there are those we saw speaking of
limitations. We can then name in IDA this function with a more meaningful name: press N over it and write
CheckStatus.
After this call the program takes two directions:
1) Call the function sub_1002580with argument 1 (push 1).
2) Go on with the routine.
Option 1) ends calling the sub_1002580with parameter 1 pushed on the stack:
.text:01003A58 push 1
.text:01003A5A call sub_1002580
If you go looking at the sub_1002580 you will see that its calling NtTerminateProcessand that the argument
pushed on stack is passed to it as exit code. IDA identified the local argument for you marking it as arg_0 and
interestingly if you highlight it with the mouse it also highlights each usage of that name in the following code.
.text:010025AD mov eax, [ebp+arg_0]
.text:010025B0 push eax
.text:010025B1 push 0FFFFFFFFh
.text:010025B3 call ds:NtTerminateProcess
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
6/38
PAGE 6REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The automatic analysis IDA performs on function is really handy
and allows to statically following the parameters of a function.
We can then rename the function sub_1002580into a more meaningful TerminateStart.
The function start.exe call just before the function CheckStatuscall two other functions:
One is the function sub_1002FB0, which is interesting because launches the program control.exe as inFigure 5.
Figure 5 start launches control.exe
The program is passed as argument of the function SbieDll_RunFromHome(x,x,x,x) which is a function
exported by SbieDll.dll. Start.exe also creates here some mutex to save from multiple instances of the program.
IDA fortunately was able to understand that the function SbieDll_RunFromHomeneeds 4 parameters.
Note 1: One advantage of IDA is
the easiness with which you canrename functions once you
understand what are they used
for. This allows to betterunderstand the code and
immediately recognize a functionwhen it used. The same
functionality is offered by OllyDbgbut actually rarely used. Also due
to the easiness with which the UDDfiles get overwritten (each time the
original exe is changed the UDD isrecreated, except if you have a
proper patch to disable thisfeature).
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
7/38
PAGE 7 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The second call is at loc_1003A25 where the sub_10038E0 retrieves the parameters from the start.exe
command-line and launches the program given to start through its command-line, using ShellExecuteExW.
Interestingly IDA also recognize the SHELLEXECUTEINFOelements of the call, you can see the following in IDA. The
code starting at loc_1003908stores the command-line into the buffer Dest. This buffer will be used later.
We then completely understood what start.exe does:
1) launches control.exe using SbieDll_RunFromHome;
2) creates some mutex to control multiple istances;3)
retrieves from the command-line the name of the program which must be sandboxed and launches it
using ShellExecuteEx, the name of this program is stored in Dest;
4) does some checks of expiration and validity in a function we renamed CheckStatus.
2.1.Deeply looking at CheckStatus routine
At a first sight one simple solution appears to patch the CheckStatus function or to patch the caller of thisfunction. I must immediately say that this option wont work, and the limitation will remain in place.
Still using IDA we have a better look at the routine CheckStatus. The function immediately calls the
SbieApi_StartProcess(x,x,x):the call is exactly like this:
SbieApi_StartProcess(Dest, var_8, var_4)
var_8and var_4are two local variables IDA recognized for us and are
initialized here:
.text:0100315E mov [ebp+var_8], offset hToken
.text:01003165 mov [ebp+var_4], offset Token
If you follow the variables hToken and Token you will find that arerespectively crated by a call to CreateProcessAsUserW and a call to
SetThreadToken. Destis instead the process being sandboxed.
This function returns its result in eax (as usual for the functions return values compiled from C), eax (actually axonly) is then moved to var_414, var_414 is immediately checked against 0. If its equal to 0 the function
SbieDll_InitProcess()is called.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
8/38
PAGE 8REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Otherwise var_414is repeatedly compared versus some constants.
loc_10031E0:cmp [ebp+var_414], 0C0000021hjnz short loc_10031F3
loc_10031F3:cmp [ebp+var_414], 0C0000268hjnz short loc_100322D
loc_100322D:cmp [ebp+var_414], 0C0000259hjnz short loc_100326E
All these constants are driving the CheckStatusto expired or limited trial messages.
Of course patching at this level is useless because only changes the message to the user, the action has already
not been performed at this level: what we should do is to understand why the SbieApi_StartProcessreturns a
value of ax!=0.
The constants we can identify are then (we can also rename them using IDA):
0h no errors calls also SbieDll_InitProcess()
0C0000021h
ok, no errors, moves al=1 and no other calls. So not a good value but not a limitationitself
0C0000268h you have been using sandboxie for more than 30 days.. 0C0000268h=UNREG_30DAYSLIMIT
0C0000259h The unregistered version doesn't support more than one sandboxie...0C0000259h=UNREG_MORESANDBOXIE
We must understand what the function SbieApi_StartProcess does and generally what all the functions of the dll
SbieDll.dll do.
2.2.Analyzing the dll SbieDll.dllWe understood all the things we said, using IDA and some logic. The dll SbieDll.dll is important to deeply
understand where the check of trial-vs-full is done. Just then open this dll with IDA again and let it analyze.
The function SbieApi_StartProcessis quite simple, seeFigure 6 and does not allow any further investigation or
any particular guess: starting from the end of the function we can climb backward to understand where the
values are got from: the function return its result in eax. eaxis modified at the following instruction:
loc_7D23B1C1:.text:7D23B1C1 mov eax, [ebp-5Ch]
[ebp-5Ch]is changed a little before at:
.text:7D23B177 call sub_7D23ABA0
.text:7D23B17C mov [ebp-5Ch], eax
.text:7D23B17F cmp dword ptr [ebp-5Ch], 0
The call sub_7D23ABA0is what we need to investigate further..
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
9/38
PAGE 9 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 6 - function SbieApi_StartProcess(x, x, x)
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
10/38
PAGE 10REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The call sub_7D23ABA0is a simple function that initializes a driver called \\Device\\SandboxieDriverApi, if not
already initialized.
At location 7D23ABA6theres a compare that calls NtOpenFileusing the above string (actually opens the driver
SandboxieDriverApi).
.text:7D23ABA6 cmp drvFileHandle, 0FFFFFFFFh
If drvFileHandle is already opened (!=-1) the function just calls NtDeviceIoControlFile, which is an API that
sends requests to the driver:
The NtDeviceIoControlFile service is a device-
dependent interface that extends the control thatapplications have over various devices within the
system. This application programming interface (API)
provides a consistent view of the input and output
data to the system while still providing theapplication and the driver a device-dependent
method of specifying a communications interface
(seeFigure 7).
Even if documentation tells that its a deprecatedfunction is still used by windows as kernel level and
might be used. What is important among the
parameters is the IoControlCode:
Code that indicates which device I/O control
function is to be executed.
The IoControlCodeused is always 222007h in the SbieDll dll.
Figure 7 - Documentation of the NtDeviceIoControlFile
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
11/38
PAGE 11 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
We can then rename this call to a more meaningful name, I used SbieDrv_222007h, just to be able to find itimmediately.
What is needed is to understand what are the other values passed to the API. Todo this we will use our beloved OllyDbg.
Open start.exe into OllyDbg and place a breakpoint at 7D23AC40 (call
ds:NtDeviceIoControlFile) into the SbieDll.dll
What you will see is that the InputBuffer local variable is apparently the only way
the driver has to communicate back the results of the call.
0006F8E0 0006F914 |Arg5 = 0006F914 IoStatusBlock0006F8E4 00222007 |Arg6 = 00222007 IoControCode0006F8E8 0006F970 |Arg7 = 0006F970 InputBuffer0006F8EC 00000040 |Arg8 = 00000040 InputBufferLength
Before reassuming the conclusions we come so far let also go at the
beginning of the function that now we called SbieDrv_222007h. Press X tosee all the references to this function and you will see that it is called in ALL
the functions of the dll we are reversing.
Summing up these the things we discovered so far:1. We discovered that the real check of the application (which guides start.exe to a trial message or to a
normal work) is done into a driver.
2. We discovered that the driver is always called using the same service IoControlCode(22207h)
3. We discovered that apparently the return code should be into an InputBuffer.
Before moving to the next section we can understand the logic of the point 3 above. Looking at the code of
SbieDrv_222007h we can see that the value of InputBuffer comes from the caller as a parameter of the
function SbieDrv_222007h (always edx). The IoStatusBlock is always set to 0 when the call returns from the
driver then, where the result is stored?
Looking at any of the calls to SbieDrv_222007hwe see that after the call the eax is always stored as following:
.text:7D23B602 push edx
.text:7D23B603 call SbieDrv_222007h
.text:7D23B608 mov [ebp-48h], eax
.text:7D23B60B mov eax, [ebp-48h]
Looking at SbieDrv_222007hit is evident that the eax value is actually the NTSTATUSReturn
.text:7D23AC49 mov eax, [ebp+NTSTATUSReturn]
So the function SbieDrv_222007his a function that actually looks like this:
SbieDrv_222007h(DWORD *InputBuffer) {extern DWORD drvFileHandle;DWORD NTSTATUSReturn=0;if(drvFileHandle==-1) {
UNICODE_STRING str;RtlInitUnicodeString(&str, L"\\Device\\SandboxieDriverApi").
InitializeObjectAttributes(&oa, ...);NtOpenFile(&drvHandle, &oa,...);
}NTSTATUSReturn=NtDeviceIoControlFile(drvFileHandle, 0, 0, 0,
IoStatusBlock, 222007h, &InputBuffer, 40h, 0,0);return NTStatusBlock;
}
You can decompile it easily looking at the code structure. Usually this decompilation exercise helps fixing
concepts.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
12/38
PAGE 12REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Finally to conclude this trip into the dll we need to fix two left concepts:
1. We landed here looking for the code of the APISbieApi_StartProcess so we need to jump back
looking for the caller, how the parameter InputBufferis created.
2.
Do all the other APIs work like this?
2.2.1
How the InputBuffer is crafted
UsingFigure 6 we can see that the parameter of SbieDrv_222007h is actually stored in edx. Edx comes from
[ebp-40h], this is a dynamic element on the stack then we must stop here wondering on IDA and go into OllyDbgagain to see which is the value given to the function.
We can place a breakpoint at the following piece of code.text:7D23B177 call SbieDrv_222007h
And see what OllyDbg reports on the stack:
The value of edx points to the value 12340006 which is pushed at 7D23B13F on the stack.
.text:7D23B13F mov dword ptr [ecx], 12340006h
This is the service we request to the driver!
So the next logical step will be to enter the driver and look how it works, to see which the correct service
dispatcher is and then patch it correctly. We will learn some basic concepts on reversing of the drivers and
patching it correctly.
We left the other question: Do all the other APIs work like this? The answer is yes, all the dll exports as similar: craft
a proper InputBufferwhich is passed to the driver and then the result is forwarded to the caller (start.exe or
control.exe).
3. Looking at the driver SbieDrv.sys
Time has come to worry of the real core of the protection, where the work is performed and the registration
checked.
Open SbieDrv.sys with IDA and let it analyze. This time we cannot anymore use OllyDbg to check anything,
because drivers can only be debugged using a Ring0 debugger like SoftICE or Syser. We want anyway
concentrate on the use of IDA as static analyzing tool, so we will discover that we will not need any Ring0
debugger to fully defeat the program.
If you understood the discussion till now, you should be confident that searching for one of the constants used as
InputBufferby the SbiApiDll should do the work: try searching for anyone of these constants (e.g. 12340006h)
and you will not find anything!
But we find something instead searching for the service descriptor we found earlier: 222007h. We find it here:
.text:0001113B cmp dword ptr [eax+0Ch], 222007h
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
13/38
PAGE 13 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The constant is referenced into a function IDA identified as sub_110F0(int,PIRP Irp).
The function sub_110F0 is the real core of our driver and what allow us to find the final handlers of the events
called by the SbieDll.
We now want to analyze the function sub_110F0, starting from the end: it ends with a call to IoCompleteRequest
and returns in eaxthe value returned by this API1: seeFigure 8.
Figure 8 - end of function sub_110F0, call to IoCompleteRequest
The drivers dispatch of events more or less works like the
following [2].. The I/O Manager creates an IRP object
describing the I/O request and sends its pointer to the
device driver in as the pIrp parameter. It's then
responsibility of the device driver how to handle this IRP. At
the end of the function handling the request we are
supposed to find a call to IoCompleteRequest, indicating
the driver has completed IRP processing and returns it to theI/O Manager2.
The IoCompleteRequest ends and the I/O manager can
delete the message or leave it if more processing is required
by other drivers (usually used in filter drivers). If the result is a
STATUS_SUCCESSthe device is ready to accept another I/O
requests.
The function sub_110F0 has several typical things:
1. ends with a call to IoCompleteRequest
2. receives as input a pointer to an IRP object
3. Is directly called by the start function of the driver in:INIT:00023D69 call sub_23040INIT:00023D6E mov bl, al
And once inside the sub_23040 it is initialized here:INIT:000230D5 mov dword ptr [edx+70h], offset DispatchMessage
So we finally discover that the sub_110F0 is the driver DispatchRoutine()!
A suggestion for a more general approach: usually for drivers it is better to not search for immediate constants in
driver as I did for DispatchRoutine, sometimes due to optimization in DDK, the code will be generated similar to
this:
1mov [ecx+18], esi IoStatus.Status (this is same code that returns from Dispatch routines)2 I found an implementation of IoCompleteRequest here: http://www.reactos.org/pipermail/ros-diffs/2006-
June/012842.html
Note 2: Before going on with the analysis stop
to think to the calling stack we discovered sofar:
This is the calling tree:
Start.exeStart() {
CheckStatus();SbieDll::SbieApi_StartProcess(x,x,x);
SbieDll::SbieDrv_222007h(12340006h);
..then the driver is called.
http://www.reactos.org/pipermail/ros-diffs/2006-June/012842.htmlhttp://www.reactos.org/pipermail/ros-diffs/2006-June/012842.htmlhttp://www.reactos.org/pipermail/ros-diffs/2006-June/012842.htmlhttp://www.reactos.org/pipermail/ros-diffs/2006-June/012842.htmlhttp://www.reactos.org/pipermail/ros-diffs/2006-June/012842.html -
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
14/38
PAGE 14REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
mov eax, [eax+0ch] Parameteres.DeviceIoContrl.IoontrolCodesub eax, 2200000hcmp eax, 1etc.
and the constants are lost. This same approach will be found later when looking at the services codes, all starting
with 12340000h.
What you should do is in DriverEntry to locate code which performs this:
mov esi, [ebp+4] ; pDriveObjectmov [esi+38], offset CreateCloseHandlermov [esi+40], offset CreateCloseHanlermov [esi+70], offset DispatchHandlermov [esi+34], offset DriverUnload
This will bring you right to dispatch routines in the driver, all the times. For example for this specific driver this part of
code is located at loc_230AA, seeFigure 9.
Figure 9 - where main functions of driver are assigned
3.1.Deeper look at the DispatchRoutine
If you follow the structure of the DispatchRoutine it is easy to see, with IDA, that theres an initialization loop I
shown inFigure 10.This loop starts from a location called unk_22000 and stores into var_24 a vector of function
pointers (the var_24 can be labeled as vptrTable_unk_2200), until the table ends with a DWORD o zeros (actually
the end is at 000220C0). If you look at the location unk_22000 you will see that its a table of functions, mostprobably the services of the driver (we will verify this later), seeFigure 11.
What we can do now is then to group all the nodes of this loop to shorten the
DispatchRoutine. We have to select the nodes underlined inFigure 10 holding shift
button and then, using right click, select the menu Group Nodes. We then enterthis text into the new node:
Initialize the unk_2200 table of function pointers.
jz if the table ends
This initialization is done only in case of error of the driver, so only at first launch
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
15/38
PAGE 15 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 10 - DispatchRoutine initialization loop
Figure 11 - early elements of location unk_22000
What we obtain is then a more simple view of the DispatchMessage()routine, seeFigure 12. Figure 12 also shows
that the table unk_2200is read into memory only the first time when the driver doesnt find it: the driver goes intoerror mode calling KeBugCheckEx, otherwise the driver normally handle the request calling IoCompleteRequest.
The call to BugCheckExis important:
When a driver goes into error mode the KeBugCheckEx
mode is the last resort the driver can take to adjust its status
and avoid wild BSODs. The KeBugCheckEx routine brings
down the system in a controlled manner when the callerdiscovers an unrecoverable inconsistency that would
corrupt the system if the caller continued to run.
The function is called when the pointers contained into
unk_2200are not loaded in memory; the driver sets a BSOD
(Blue Screen of Death) reporting some useful information.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
16/38
PAGE 16REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The KeBugCheckExhas these parameters:
VOIDKeBugCheckEx(IN ULONG BugCheckCode,IN ULONG_PTR BugCheckParameter1,IN ULONG_PTR BugCheckParameter2,IN ULONG_PTR BugCheckParameter3,
IN ULONG_PTR BugCheckParameter4);
Any parameter BugCheckParameterX supply additional information, such as the address and data where a
memory-corruption error occurred, depending on the value of BugCheckCode. The most interesting is the
parameter BugCheckParameter2 which is the base of the InputBuffer, its missing and the error message
reports it!
Figure 12 - Condensed view of DispatchMessage
We are not successfully reversed the structure of the DispatchMessageand the meaning of unk_2200table of
functions.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
17/38
PAGE 17 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The unk_2200table of functions is actually a table of the services offered by the driver, the functions are called
using the value InputBufferpassed as argument to the NtDeviceIoControlFile; the offset of the table is got
subtracting the value 12340000h to InputBuffer.
For example then:
1.
The constant 12340001h is used in the
SbieApi_GetVersion2. The first position of the unk_22000 table is the
function sub_11240
3. We can rename it as HGetVersion. This is the
handler of the service 12340001h
The same can be done with all the other function pointers
starting from unk_22000. We can rename this location
pressing N over it with IDA and call it Services_Table.
Generally speaking then the formula to get the correcthandler is this one:
Handler = *Services_table + (*InputBuffer-12340000h)*8h
For example for the SbieApi_StartProcess() we have
InputBuffer=12340006hHandler= 00022000h + (12340006h 12340000h)*8h = 00022030h sub_1E790 HStartProcess
Better looking at the Services_Tableyou can find that theres another interesting way to discover what wejust
described:
.data:00022030 db 6
.data:00022031 db 0
.data:00022032 db 34h ; 4
.data:00022033 db 12h
.data:00022034 dd offset sub_1E790
The element at 0x00022030is the number of the handler minus the offset 12340000h.
We now have all the elements to correctly track down the events of the program through the SbieDll APIs.
The most relevant handlers are the following ones (with the final name given in IDA):
SbieApi_StartProcess 12340005h 5h sub_1E790 HStartProcess
SbieApi_SetLicense 12340006h 6h sub_1CA50 HSetLicence SbieApi_SetUserName 12340015h 15h sub_132D0 HSetUserName
SbieApi_GetLicense 12340004h 04h sub_1C9F0 HGetLicense
SbieApi_QueryConf 1234000Fh 0Fh sub_13080 HQueryConf
The complete table is the following one (just the functions):
.data:00022000 Services_Table db 1
.data:00022004 dd offset HGetVersion ; handle 12340001
.data:0002200C dd offset HGetWork
.data:00022014 dd offset HLog
.data:0002201C dd offset HCallZero
.data:00022024 dd offset HGetLicense
.data:0002202C dd offset HSetLicence
.data:00022034 dd offset HStartProcess
.data:0002203C dd offset HQueryProcess
.data:00022044 dd offset HQueryBoxPath
.data:0002204C dd offset HQuerProcessPath
.data:00022054 dd offset HQueryPathList
.data:0002205C dd offset HEnumProcess
.data:00022064 dd offset HDisableForceProcess
.data:0002206C dd offset HGetInjectSaveArea
Note 3: We can now complete the callingtree of Note 2:
Start.exe
Start() {CheckStatus();
SbieDll::SbieApi_StartProcess(x,x,x);SbieDll::SbieDrv_222007h(12340006h);
SbieDrv::DispatchMessage()
SbieDrv::HStartProcess()
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
18/38
PAGE 18REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
.data:00022074 dd offset HGetSetDeviceMap
.data:0002207C dd offset HRenameFile
.data:00022084 dd offset HUsedInternally_to_driver
.data:0002208C dd offset HCreateDirOrLink
.data:00022094 dd offset HDuplicateObject
.data:0002209C dd offset HHookTramp
.data:000220A4 dd offset HReloadConf
.data:000220AC dd offset HQueryConf
.data:000220B4 dd offset HSetUserName
4. The final work: patching the driver
We are now able to track the elements of the keyboard down to the driver services; we must understand how to
patch a driver. I strongly suggest to use VMWARE or any other virtual PC platform to do your trials, its faster to
reboot and safer. Theres also another reason, the driver is loaded the first time the program loads it and neverunloaded until a new reboot is done, so new patches will become active only after a reboot of the PC, virtual or
real.
4.1.Patching the handler of StartProcess
In Section 2.1 we already identified some constants we called UNREG_30DAYSLIMIT andUNREG_MORESANDBOXIE. Of course now we find these same constants in the function HStartprocessfunction of
the driver.Figure 13 reports the details of the two constants we identified, but this time in the driver SbieDrv.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
19/38
PAGE 19 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 13 - HStartProcess details on constants returned
Looking atFigure 13 we can say that for the UNREG_30DAYSLIMITwe must fix the call sub_1CB40because this
function is called several times around the code. According to code above if al=0then UNREG_30DAYSLIMITis
set. So sub_1CB40must return al!=0always.
If you look at the code of the function sub_1CB40, there's only one place where alis set to 0
.text:0001CB85 jz short loc_1CB8F ; this one becomes a JMP
.text:0001CB80 loc_1CB80: ; CODE XREF: sub_1CB40+36j
.text:0001CB80 mov al, [ebp+arg_0]
.text:0001CB83 test al, al
.text:0001CB85 jz short loc_1CB8F
.text:0001CB87 xor al, al
.text:0001CB89 mov esp, ebp
.text:0001CB8B pop ebp
.text:0001CB8C retn 4
.text:0001CB8F ; --------------------------------------------------------------------------
.text:0001CB8F
.text:0001CB8F loc_1CB8F: ; CODE XREF: sub_1CB40+45j
so the patch1 on the driver is: 0001CB85 JZ becomes a JMP
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
20/38
PAGE 20REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The other limitation, connected to UNREG_MORESANDBOXIE has a similar structure, but involves the function
sub_1E6D0, which must return al!=0as well to be good for us.
This time this specific function is only called in
HStartProcess, but we patch it also.
The last section of the sub_1E6D0is:
.text:0001E74A loc_1E74A:
.text:0001E74A mov edx, off_223F4
.text:0001E750 push edx
.text:0001E751 push offset unk_227CC
.text:0001E756 call sub_18210
.text:0001E75B mov al, [ebp+var_1]
.text:0001E75E pop esi
.text:0001E75F mov esp, ebp
.text:0001E761 pop ebp
.text:0001E762 retn
.text:0001E762 sub_1E6D0 endp
the register alis set here:
.text:0001E75B mov al, [ebp+var_1]
But the var_1is set to 0 here:
.text:0001E745 mov [ebp+var_1], 0
So the Patch must be done at 0001E73B
jnz short loc_1E745 NOP
4.1.1
A deeper look at the HStartProcess routines
The call sub_1CB40has an argument, as IDA underlines.
proc nearvar_20= word ptr -20hCurrentTime= LARGE_INTEGER ptr -8arg_0= byte ptr 8
This argument is called arg_0and is a DWORD.
Inside the code of this function I can see that this argument is used to decide whenever to return a value of al=0
or not.
Particular important is this piece of code:
loc_1CB80:mov al, [ebp+arg_0]test al, aljz short loc_1CB8F ; JMP and the function will not return al=0 anymore
It is equivalent to the following decompiled piece of code:
loc_1CB80:if (arg_0 == 0) goto loc_1CB8F;
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
21/38
PAGE 21 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
So to have this call to return a value correctly (no badboys) we have to push a value of 0 as argument.
Interestingly the call references to sub_1CB40are these:
p sub_1E240+8 call sub_1CB40p sub_1E6D0+6 call sub_1CB40
p HStartProcess+31 call sub_1CB40
The first two gives to the function a value of 1, like for example:
.text:0001E246 push 1
.text:0001E248 call sub_1CB40
The third one instead is inside HStartProcess, the detail of this third one is the following:
.text:0001E7C0 loc_1E7C0:
.text:0001E7C0 push ebx
.text:0001E7C1 call sub_1CB40
the value of ebx is pushed to the function and few lines
above it is xored in this line:
.text:0001E79A xor ebx, ebx
Evidently the 30 days limit is build in into the application
and to fix it the option is then to change this last xor into
a MOV EBX, 1
The third way to Patch is to patch at 0001E79A like the following:
xor ebx, ebx mov ebx, 1 or better to save space a mov bl,1 (B3 01) which fits into the available
space.
4.2.Patching the handler of SetLicense
You surely have found that theres a menu in the program that allows inputting of a serial number and username.
Theres also a corresponding function in the SbieDll dll called SbieApi_SetLicense. If you look with OllyDbg you
will immediately find that it is called by control.exe to handle the result of the registration, seeFigure 14.
The function (actually we know thats the driver which handle all) returns a constan t all the times equal to:
0C000026Ah. This same constant is found in HSetLicense, as evident fromFigure 15.The patch is then very simple
this time:
.text:0001CAC3 jz short loc_1CAD3jmp short loc_1CAD3
The result of the patch is shown inFigure 16.
Moreover the following code:
.text:0001CAB6 push ecx ; wchar_t *
.text:0001CAB7 push edi ; wchar_t *
.text:0001CAB8 call ds:_wcsicmp
Looks very promising for another patch: the insertion of a call to DbgPrint3 in order to fish the real serial over a
Dbgmessage...I will leave this for you
3The syntax of DbgPrint is almost the same of a printf
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
22/38
PAGE 22REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 14 - call of Sbie_SetLicense in control.exe
Figure 15 - portion of HSetLicense in the driver that will be patched
Figure 16 - result of patched HSetLicense
The result of this modification is not only a successful registration check, but also the removal of all the other
limitations we saw at the beginning of this document, seeFigure 17.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
23/38
PAGE 23 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 17 - final result of patchings
4.3.Patching the handler of GetLincense
The SbieApi_GetLicenseneeds a little more understanding of the program flow. First of all open OllyDbg and
place a breakpoint in control.exe where the badboy message is composed, seeFigure 14.I placed a breakpoint
at 0100E0B1.
The code is the following:
On the stack at location [EBP-1B4] the program control.exe pushed the
string I shown in Figure 17, the call to SbieApi_GetLicense simply after the
call to the driver if the result is different from 0, sets to 0 the first byte of the
location [EBP-1B4] invalidating the string. The code at 0100E0B6 simply
checks this location and if not zero skip the bad boy message.
In other worlds, it looks like the following pseudo-code:
dword var=0;SbiApi_GetLicense(&var);if(var==0)
else
What the function SbiApi_GetLicensedoes is to call the driver passing a buffer, it writes 0 at the first byte if the
program is not registered.
The SbieApi_GetLicense is reported inFigure 18.The portion of code circled is the one responsible of zeroing
out the first byte of the argument on the stack, specifically the second mov. This portion of code is executed onlywhen eax=0.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
24/38
PAGE 24REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 18 - SbieApi_GetLicense
Figure 19 reports the disassembly view of HGetLicense. Into this function as you can see there are two possiblepaths: the correct one, on the right, ends with a xor eax, eaxwhich is what we needed to recognize it. So the
patch this time forces the execution of this branch:
Patch.text:0001C9FA jnz short loc_1CA01 jmp short loc_1CA01
Note 4: Blacklists are usual in programs and it is not rare to findthem into a program. This one is not an exception:
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
25/38
PAGE 25 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 19 - HGetLicense
This last modification allows to nicely seeing our name in the about box:
Note 5: Actually patching only HGetLicense
and HSetLicense is enough to defeat checks,but the previous discussion on HStartProcess is
useful to better understand the method and
the discussions on drivers.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
26/38
PAGE 26REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
4.4.Fixing the header of the driver: checksum of PE Header
Now many of you know that into the PE header file theres a checksum field that is the checksum (CRC32) of the
whole file [3], see alsoFigure 20.
Figure 20 - Checksum value in PE header of sys driver
The PE files headers include a CheckSum field which is located into the:
IMAGE_NT_HEADER IMAGE_OPTIONAL_HEADER CheckSum
This value is an overall checksum of the whole file, often not set and left to 0x0000 by most compilers and thus
doesn't happens often to worry about it, but sometimes this value is used to check if there have been alterations
in the executable file. There is for example an API, MapFileAndCheckSum(), which calculates the real checksum
of a PE file and reports also the value stored into the PE Header. It is then simple for simple protectors to detect
alterations of a PE file, even of a single byte.
It's a simple technique that advanced protector doesn't use too often and you can of course intercept this API
and modify it online or skip its call, but for example with PocketPC smartphones or system drivers this check isdone by the operative system, so you simply have no choice to intercept this check and the only way is to fix the
value stored in the PE file header. The system uses this value to check the integrity of a driver, before loading it. If
you patch a driver and simply load it the result is that it will not be loaded by the system because the storedchecksum and the calculated one are different.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
27/38
PAGE 27 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The MapFileAndCheckSumfunction computes the checksum of the specified file.
DWORD MapFileAndCheckSum(PTSTR Filename,PDWORD HeaderSum,PDWORD CheckSum
);
Parameters
Filename[in] Pointer to a null-terminated string that specifies the file name of the file for which the checksum is
to be computed.
HeaderSum[out] Pointer to a variable that receives the original checksum from the image file, or zero if there is an
error.
CheckSum[out] Pointer to the variable that receives the computed checksum.
You then should fix this field of the patched sys file and store the value calculated by the above API.
Luckily a few months ago I developed a Checksum Fixer program [4] which does exactly this thing: I met a
program that was checking against this value in the header to see if it was patched or not and decided tocreate this tiny tool.This program simply does this fix conveniently. Already other tools have this functionality (LordPE for example), but
I just wanted a fast program able to fix this checksum in a click (e.g. with LordPE you have to do at least 5, 6
clicks).
The usage of the program is really simple: you can launch it directly and drag&drop the patched sys file, or open
using buttons or do all automatically on the command-line.Figure 21 shows the result
Figure 21 - Checkum Fixer result on patched sys file
You can also automatically fix all using this syntax:
CheckSum.exe sbieDrv.sys -fix
Note 6: Before trying out any patch on the
driver you must fix the checksum header valueof the sys file and then restart the system to
load the modified driver.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
28/38
PAGE 28REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
5. Keygenning the Program
This is our last and highest levels result in our reversing journey into SandBoxie. We can keygen the program
without even touching Olly, or, better touching it just to find some evidences we will use for building the keygen.
First of all we need to find the serial generation routine: it should already be clear at this stage that it is into the
driver. Figure 15 shows the most important part of the function HSetLicense: this function is responsible ofunderstanding if the license code given is correct or not. Figure 15 reports the point where we patched the
function so as to accept any serial. Of course the piece of code above the patch is responsible of the serial
calculation. If you further analyze it, still using IDA, you get the result ofFigure 22.
Figure 22 - Serial Calculation in HSetLicense
I properly commented all the parts of the code, it should be clear that the sub_1C320 is the routine that
calculates the serial number, which is then compared with the serial given by the user through a _wcsicmp, that is
a wide char (Unicode) comparison of strings not case sensitive. We can then rename the sub_1C320 with
SerialCalculation.
If you go into the SerialCalculation you can see that IDA
identified two arguments for the function, called arg_0and arg_4.
These two arguments are passed through the activation record
mechanism typical of any call with the Intel platforms. Depending on
the calling convention used by the compiler/language (thepossibilities are VisualC++ and C in general or Borland and Pascal)
the arguments are pushed on the stack in different order. I knowhere, thanks to PEiD, that the driver was compiled using VisualC++
then I used the C parameter pushing convention to restore the
prototype of the SerialCalculationroutine. The result is:
SerialCalculation(UCHAR *name, UCHAR *serial);
There are also two local variables which
will be used in the function, var_8 and
var_4.
I know that the two parameters are
Unicode strings because the programControl.exe takes them from the
DialogBox in Unicode format and with
that format passes them to the driver.
The SerialCalculationfunction is quite
complex and we will not analyze it, what
we will do instead is to understand the
general behavior and understand how to
extract it from the driver.
Note 7: There are two possible methods compilers use to push
arguments of a function on the stack [5]: C and Pascal callingconventions. Given the function dummy(Arg1,Arg2,..,Argn) the
two possibilities are:
C Calling Convention Pascal Calling Convention
Assembler push Argn
..
push Arg2push Arg1
call dummy
push Arg1push Arg2
..push Argn
call dummy
Stack
Arg1Arg2
Argn
Argn...
Arg2Arg1
The parameters will be sorted on the stack or the code.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
29/38
PAGE 29 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The most interesting part of the function is shown in Figure 23,where we understand that the serial is actually
calculated using a string of valid characters (off_223F0), that it is stored in the variable arg_4 and that it is long 0Eh
characters (an Unicode string of 6 characters, that is what we experience using Sandboxie).
Figure 23 - ending part of the SerialCalculation
5.1.Testing the atomicity of the SerialCalculation routine
The Atomicity of a function is an important property of any function that you must verify each time you want to
code a keygen. An Atomic function is simply a function that doesnt rely for doing its work from externalinformation, except those passed as its arguments, and which actions are only affecting the return value or the
parameters.
Figure 24 - General schema of a Function to test Atomicity
Function
Function Function
Called Functions
External Dependencies
(constants, global variables)
Parameters Results
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
30/38
PAGE 30REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Figure 24 reports the structure of a general function where, beside the normal flow of Parameters and Results,
there are two side flows of information: the Called Functions and the External Dependencies (constants or global
variables). These flows can also be bi-directional depending on the possibility of the Function to read and
eventually write some values. In order to create a keygen you must understand and document all these flows,once isolated the function responsible of the serial number calculation. The keygen must re-create into a
separated program the same environment the Function wants, otherwise it will not work4
This property allows taking the function as it is, in assembler, and extracting it from the rest of the program, withouttoo much problems. A first overview of the function reveals that this function is atomic, but we will verify it also toshow the method for more complex cases and for the drivers specifically.
Easy tests in IDA reports that the function SerialCalculation doesnt call any other function and depend only fromthe external constant at off_223F0. We anyway need to test if it can live on its own, with the proper arguments!!
Usually OllyDbg is very handy when you have to verify the atomicity of a function, but we are now reversing a
driver, which cannot be loaded into a Ring3 debugger. What we need is to properly modify the driver so as
OllyDbg will be able to load it (see also [8]), even if not completely execute it.
The method simply changes the *.sys PE Header so as to transform the driver into a normal Dll or a normal
executable: remember that a driver is a native executable or dll, linked to native dlls (usually hal.dll and
ntoskrnl.exe). We will use CFF Explorer to change the driver:
1.
Change the File Header Characteristics and tick File is a DLL
2. Change the Optional Header SubSystem and select Windows GUI
3. Change the Data Directories Import Directory RVA and Import Directory Size to 0, to erase the import
tables of system dlls
4If this operation is too complex or long you can always create an Oraculum or self-keygen [6, 7]
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
31/38
PAGE 31 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
Now your driver is ready for OllyDbg, of course it will not work, but we can open into OllyDbg and work it out for
our needs.
5.2.
Loading the modified driver into OllyDbg
Now we can open the driver within OllyDbg and go to where the function HSetLicense calls the function
SerialCalculation.
The address is not the same shown in OllyDbg (see Note 8), and
then we jump here:
003BCAAC . 50 PUSH EAX003BCAAD . 56 PUSH ESI
003BCAAE . E8 6DF8FFFF CALL SbieDrv.003BC320
Then we move the execution point just here, using Ctrl-Gray-* or
the context menu Set New Origin Here.
The result is that we skip all the rest of the code and will gosimulating the driver execution, when it calls the SerialCalculation
routine.
Using IDA we supposed which are the meanings of EAX and ESI and we can then now modify them so as to point
somewhere in memory, useful for our test.
These are the steps I will cover now, being the first already done:
1. modify the sys so as it can be loaded into OllyDbg.
2. place the execution point at
003BCAAC . 50 PUSH EAX
using CTR+GRAY+* or the menu "set new origin here"
Generally speaking jumping the execution point wheres the call of the function that will generate theserial number, is a good trick. This allows skipping all the rest of the program and allows us to test the
input conditions to the function so as to prepare for the keygen we are going to build. Its like in asurgical operation where we want to transplant a living organ from the program to the keygen
3. find a good place where to let them point, look for the memory map and find a place with all 0000 ... forexample I used:
EAX=3C2440where there's space for the new string with the serial
ESI=3C2420where I wrote in Unicode format "Shub-Nigurrath"
4.
change EAX and ESI so as to point respectively to the name in Unicode and to a position where to store
the serial number.
Note 8: Due to the modifications we did thedriver, it is not loaded at the same addresses
IDA shows, we must then use the file offsets.
You then need the OllyDbg plugin OllyAdvanced from Markus TH-DJM, whichmodifies, among the other things, the goto
menu, adding the possibility to jump to file
offsets.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
32/38
PAGE 32REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
5. execute step by step the call at
003BCAAE . E8 6DF8FFFF CALL SbieDrv.003BC320
and stop at the end.
You can see that the function properly filled the buffer pointed by ESI with a serial number.
003C2420 53 00 68 00 75 00 62 00 2D 00 4E 00 69 00 67 00 S.h.u.b.-.N.i.g.003C2430 75 00 72 00 72 00 61 00 74 00 68 00 00 00 00 00 u.r.r.a.t.h.....003C2440 42 00 47 00 4E 00 4B 00 52 00 41 00 31 00 00 00 B.G.N.K.R.A.1...
and the registers too are extremely interesting:
6. Verify that works.
The function SerialCalculationiseasilyAtomic and can be extracted from the driver!
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
33/38
PAGE 33 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
5.3.Coding the keygenerator
The last step of this drama is to code a keygenerator which calls the function and shows the result. There are
some tricks to learn in order to do it.. First of all I will use the naked functions, I already explained in details in [9]. I
will not then cover this argument again here.
Second important thing is to copy the whole code of the SerialCalculation function and paste it into ourcode and edit it like following:
1. Remove the trailing addresses, leaving only the assembler instructions (remove all those things like
.text:0001C320). The format of the assembler instructions shown by IDA is the same supported by the
C language by means fo the __asm instruction. This is very handy, because you can copy and paste
quite effortlessly the code from IDA to a C program.
Change the relative addresses of the parameters and local variables of the function. The local variables
are not anymore referenced as offset of the EBPregister but directly
So for example into IDA there's these lines:
mov edi, [ebp+arg_0]mov [ebp+var_4], edx
now I have instead these two lines instead:
mov edi, [arg_0]mov [var_4], edx
The offset with ebpis correctly handled by the compiler and I don't need it anymore
2. Insert the assembler into an __asm{}block and then into a naked function (see [9] for an explanation of
what are the naked functions).
Using the naked functions allows skipping the prolog and epilog instructions the compiler places tocorrectly handle the calls and the stack. This operation was already been done by the compiler that
created the call we are taking out from the driver. So our keygenerator doesnt need to add themanymore. We will leave the prolog and epilog that are already between the asm instructions of the
SerialCalculation, without even worrying of which precisely are these instructions..
3. Add all the external constants and the local variables used by SerialCalculation just outside the
function (the naked functions cannot have such variables into its body):
//string referenced into the programcharaA1b2c3d4e5f6g7[]="A1B2C3D4E5F6G7H8V9JKLMNPQRSTWXYZ" ;//simulates the offset call we saw in IDA, through a pointer holding the start//of the string..char* off_223F0=aA1b2c3d4e5f6g7;//local variables IDA identified for us and we placed them back, the routine use themDWORD var_4=0, var_8=0;
4. Assemble everything using UNICODE format strings; we saw that the arguments of the
SerialCalculation function are Unicode strings. Instead of printf use the widechar version
wprintf/wscanfor alternatively the printf/scanfwith the correct format specifier.
A note: you could also use printfbut you must correctly handle the Unicode string. For example:
wchar_t wstring=LExaxmple of string;wprintf (LI am an Unicode text, shown on not Unicode screen %s, wstring).printf(I am an Unicode text shown on not Unicode screen %S,wstring);
in this example the Unicode constant shown (I am an Unicode) is not really important, the important
is to show it on screen; the Unicode string wstringis shown correctly using wprintor the printfwith %S
format specifier. The same happens with wscanfand scanf.
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
34/38
PAGE 34REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
The result is the following piece of code..
#include#include
//prototype of the function as it is read from IDA..voidCalculateSerial (wchar_t *arg_0, wchar_t *arg_4);
voidmain() {
//unicode variableswchar_t name[255]=L"Shub-Nigurrath";wchar_t serial[8]; //serial is long 0x0E
//keep the things clean and tidymemset(name,0,sizeof(name));memset(serial,0,sizeof(serial));
wprintf(L"Enter your name (max 255):");wscanf(L"%s",name);
//call to the assembler code naked from the applicationCalculateSerial(name,serial);
//printf out the result
wprintf(L"Name: %s\n", name);wprintf(L"Serial: %s\n", serial);
}
//string referenced into the programcharaA1b2c3d4e5f6g7[]="A1B2C3D4E5F6G7H8V9JKLMNPQRSTWXYZ" ;//simulates the offset call we saw in IDA, through a pointer holding the start of the string..char* off_223F0=aA1b2c3d4e5f6g7;//local variables IDA identified for us and we placed them back, the routine use themDWORD var_4=0, var_8=0;
//The naked declaration allows to use all the assembler code as it is from IDA and to avoid//worrying of the context record of the call, it is already correctly used into the asm//instructions we got from IDA__declspec( naked ) voidCalculateSerial (wchar_t *arg_0, wchar_t *arg_4){
//The only differences with the ASM code into IDA are that the local variables are not//referenced as offset of the EBP register but directly//So for example into IDA there's these lines:// mov edi, [ebp+arg_0]// mov [ebp+var_4], edx//now I have instead these two:// mov edi, [arg_0]// mov [var_4], edx//The offset with ebp is correctly handled by the compiler and I don't need it anymore..////All the other instructions are exactly the same as in IDA.__asm{
push ebpmov ebp, espsub esp, 8push ebxpush esipush edimov edi, [arg_0]xor bl, blxor esi, esicmp [edi], simov edx, 0BADF00Dhmov [var_4], edxmov byte ptr [var_8], bljz loc_1C420
loc_1C344: ; CODE XREF: SerialCalculation+F7_jcmp esi, 66hjnb loc_1C4C0mov al, [edi+esi*2]mov cl, byte ptr [var_4]inc esi
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
35/38
PAGE 35 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
test al, 1jz shortloc_1C35Cadd cl, aljmp shortloc_1C35E; ---------------------------------------------------------------------------
loc_1C35C: ; CODE XREF: SerialCalculation+36_jinc cl
loc_1C35E: ; CODE XREF: SerialCalculation+3A_jtest al, 2mov byte ptr [var_4], cljz shortloc_1C376mov edx, [var_4]mov cl, alshl cl, 1shr edx, 8add dl, clmov byte ptr [var_4+1], dljmp shortloc_1C37A; ---------------------------------------------------------------------------
loc_1C376: ; CODE XREF: SerialCalculation+43_jadd byte ptr [var_4+1], 2
loc_1C37A: ; CODE XREF: SerialCalculation+54_jtest al, 4mov cl, byte ptr [var_4+2]jz shortloc_1C38Amov dl, alshl dl, 2add cl, dljmp shortloc_1C38D; ---------------------------------------------------------------------------
loc_1C38A: ; CODE XREF: SerialCalculation+5F_jadd cl, 4
loc_1C38D: ; CODE XREF: SerialCalculation+68_jtest al, 8mov byte ptr [var_4+2], cljz shortloc_1C3A3
mov dl, byte ptr [var_4+3]mov cl, alshl cl, 3add dl, clmov byte ptr [var_4+3], dljmp shortloc_1C3A7; ---------------------------------------------------------------------------
loc_1C3A3: ; CODE XREF: SerialCalculation+72_jadd byte ptr [var_4+3], 8
loc_1C3A7: ; CODE XREF: SerialCalculation+81_jtest al, 10hmov cl, byte ptr [var_4]jz shortloc_1C3B7mov dl, alshl dl, 4
add cl, dljmp shortloc_1C3BA; ---------------------------------------------------------------------------
loc_1C3B7: ; CODE XREF: SerialCalculation+8C_jadd cl, 10h
loc_1C3BA: ; CODE XREF: SerialCalculation+95_jtest al, 20hmov byte ptr [var_4], cljz shortloc_1C3D0mov dl, byte ptr [var_4+1]mov cl, alshl cl, 5add dl, clmov byte ptr [var_4+1], dl
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
36/38
PAGE 36REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
jmp shortloc_1C3D4; ---------------------------------------------------------------------------
loc_1C3D0: ; CODE XREF: SerialCalculation+9F_jadd byte ptr [var_4+1], 20h
loc_1C3D4: ; CODE XREF: SerialCalculation+AE_jtest al, 40h
mov cl, byte ptr [var_4+2]jz shortloc_1C3E4mov dl, alshl dl, 6add cl, dljmp shortloc_1C3E7; ---------------------------------------------------------------------------
loc_1C3E4: ; CODE XREF: SerialCalculation+B9_jadd cl, 40h
loc_1C3E7: ; CODE XREF: SerialCalculation+C2_jtest al, almov byte ptr [var_4+2], cljns shortloc_1C3FDmov dl, byte ptr [var_4+3]mov cl, al
shl cl, 7add dl, clmov byte ptr [var_4+3], dljmp shortloc_1C401; ---------------------------------------------------------------------------
loc_1C3FD: ; CODE XREF: SerialCalculation+CC_jadd byte ptr [var_4+3], 80h
loc_1C401: ; CODE XREF: SerialCalculation+DB_jmov ecx, [var_4]mov edx, ecxshr edx, 1Fhadd ecx, ecxor edx, ecxadd bl, alcmp word ptr [edi+esi*2], 0
mov [var_4], edxjnz loc_1C344mov byte ptr [var_8], bl
loc_1C420: ; CODE XREF: SerialCalculation+1E_jmov esi, [var_8]and esi, 1Fhmov ecx, 20hsub ecx, esimov eax, edxshr eax, clmov ecx, esishl edx, clpop edior eax, edxmov edx, off_223F0 ; call to the offset of valid characters forthe serial
; number..
mov ecx, eaxand ecx, 1Fhmovzx si, byte ptr [edx+ecx]mov ecx, [arg_4] ; will store the serial number into the arg_4
; It is passed to the functionas pointer to Unicode array; long0Eh
mov [ecx], sishr eax, 5mov esi, eaxand esi, 1Fhmovzx si, byte ptr [edx+esi]mov [ecx+2], sishr eax, 5mov esi, eaxand esi, 1Fhmovzx si, byte ptr [edx+esi]
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
37/38
PAGE 37 REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
mov [ecx+4], sishr eax, 5mov esi, eaxand esi, 1Fhmovzx si, byte ptr [edx+esi]mov [ecx+6], sishr eax, 5mov esi, eax
and esi, 1Fhmovzx si, byte ptr [edx+esi]mov [ecx+8], sishr eax, 5mov esi, eaxand esi, 1Fhmovzx si, byte ptr [edx+esi]shr eax, 5mov [ecx+0Ah], siand eax, 1Fhmovzx ax, byte ptr [eax+edx]pop esimov [ecx+0Ch], axmov word ptr [ecx+0Eh], 0pop ebxmov esp, ebppop ebp
retn 8
; ---------------------------------------------------------------------------loc_1C4C0: ; CODE XREF: SerialCalculation+27_jmov edx, [arg_4]pop edipop esimov byte ptr [var_8], blmov word ptr [edx], 0pop ebxmov esp, ebppop ebpretn 8;SerialCalculation endp
} //and of __asm block} //end of SerialCalculation function
The result of the program is like the following:
You can now add all the digital, amazing effects and musics if you want, or leave rude and direct as it is, but theessence is already here, the keygen works!!
-
7/24/2019 Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath
38/38
PAGE 38REVERSING OF A PROTECTION SCHEME BASED ON DRIVERS: SANDBOXIE
6. References
[1] SandBoxie 3.00.03,www.sandboxie.comor mirrored at
http://arteam.accessroot.com/tools/SandboxieInstall.exe
[2] Windows DDK version 6000.070702 help, available on Microsoft site.
[3] Portable Executable File Format Compendium v11 by Goppit,http://tutorials.accessroot.com
[4]
CheckSum Fixer v1.0 by Shub-Nigurrath,http://arteam.accessroot.com[5] Beginners Tutorial #9, Defeating Magic Byte Protection by Gabri3l, http://tutorials.accessroot.com[6] Guide on How to play with processes memory, write loaders and Oraculums by Shub-Nigurrath,
http://tutorials.accessroot.com
[7] Coding a Serial Sniffer (Oraculum) by Anorganix, ARTeam e-zine #2,http://tutorials.accessroot.com
[8] A Journey to the Center of the Rustock.B Rootkit by Frank Boldewin, 20th January 2007,http://reconstructer.org
[9]
Improving the HideDebugger function by Shub-Nigurrath,http://tutorials.accessroot.com
7.
Greetings
Greets goes out to the entire ARTeam family with its past, present and future members. A word of thank you tothe team members who took the time to read the beta version of this document and also found some importanterrors. If youve got suggestions and/or comments about this tutorial or want to contribute with something new or
simply say hi, stop by at the forum and participate to the discussions there. Again, sorry for releasing this tutorial indifferent versions, but I think additions deserve a new release of this documents.
Document History
Version 1.0First Public Release
Version 1.1Added the keygenning of the program with complete sources too
http://www.sandboxie.com/http://www.sandboxie.com/http://www.sandboxie.com/http://arteam.accessroot.com/tools/SandboxieInstall.exehttp://arteam.accessroot.com/tools/SandboxieInstall.exehttp://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://arteam.accessroot.com/http://arteam.accessroot.com/http://arteam.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://reconstructer.org/http://reconstructer.org/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://reconstructer.org/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://tutorials.accessroot.com/http://arteam.accessroot.com/http://tutorials.accessroot.com/http://arteam.accessroot.com/tools/SandboxieInstall.exehttp://www.sandboxie.com/