Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath

download Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath

of 38

Transcript of Reversing of a Protection Scheme Based on Drivers v11 by Shub-Nigurrath

  • 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/