0% found this document useful (0 votes)
111 views49 pages

Tutorial C01D - USB Over Ethernet v2.5 PDF

The document provides a tutorial on cracking the protections of the USB Over Ethernet application. It begins by examining the application's limitations and protections. Upon analysis, it is determined that the key to removing protections lies in analyzing the Windows service installed by the application, called usboesrv.exe. The document then details exhaustively analyzing the application's nag screen before focusing efforts on debugging the Windows service to reveal its protection mechanisms and find a way to fully crack the application.

Uploaded by

Leo XD
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
111 views49 pages

Tutorial C01D - USB Over Ethernet v2.5 PDF

The document provides a tutorial on cracking the protections of the USB Over Ethernet application. It begins by examining the application's limitations and protections. Upon analysis, it is determined that the key to removing protections lies in analyzing the Windows service installed by the application, called usboesrv.exe. The document then details exhaustively analyzing the application's nag screen before focusing efforts on debugging the Windows service to reveal its protection mechanisms and find a way to fully crack the application.

Uploaded by

Leo XD
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 49

USB Over Ethernet v2.5.

5
Tutorial C01D
PROTECTION: Hash / CRC / Checksum or Digital signatures, plus encryption.

Remove limitations from a Windows service: 2 devices connection,


OBJECTIVE:
15 days trial and nag screen.
Click here. In case of broken links or impossibility of finding this
DOWNLOAD:
version, please contact me by e-mail.

DIFFICULTY: Regular with some complex parts.

OllyICE, Windows Service Manager, Resource Hacker, Hash & Crypto


TOOLS:
Detector, Hexadecimal Editor.

CRACKER: SACCOPHARYNX DATE: 22/09/2010

Sections
1) Introduction
2) Getting in touch
3) Nag Screen - Exhaustive analysis
4) Looking into the Windows services (usboesro.exe)
CONTENT: 5) Name Pipes - A way of communication
6) Revealing the protections
7) Finding the Saccopharynx's Service Ripper Point to debug the Windows service startup with Olly
8) Crack the Riddle
9) Thanks

Introduction
My first undertakings with this application were two years ago, in 2008, when I needed to share a USB dongle located
in Spain when I was somewhere far beyond Europe. The aim of USB Over Ethernet (UOE) is essentially that: Providing
ability to share USB devices over LANs or the Internet and use them remotely as if they were plugged into a local PC.

Owing to the fact that the security of UOE is not reinforced by the use of software protectors like Asprotect, Armadillo
or EXECryptor, the cracking process of the application was not expected to take more than a few hours. However, it
turned into a substantial mayhem of painful surprises.

Getting in touch
As soon as the application is executed a nag screen appears to remind us how many days left for trial period:
Image 01

If the evaluation is continued, UOE finally starts but does not allow us to establish connection with more than 2
devices concurrently:

Image 02

The analysis of the EXE file with PeiD determines that no familiar protectors were used to wrap it up, and it is
tempting not to expect difficulties to get a fully functional version in a short time:
Image 03

Nevertheless, all the efforts made when patching the main application have been almost in vain. It chiefly means that
it is impossible to get a workable cracked version, but just a completely hopeless graphic user interface. The nag
screen can be passed without struggling really much with the code, but if there are no days remaining for evaluation,
not even a single device can be connected. If some days still remain, no more than two can be simultaneously shared.
In a few words, there is not a positive approach to reverse UOE if only looking into the main executable file.

Furthermore, it should be mentioned that it is not mandatory to operate over Ethernet or the Internet to establish
connections with USB devices, since it is possible to make use of those USB devices installed in the host machine by
connecting to 127.0.0.1. Thus, local devices are also treated as remote devices. Below there is a video that shows
how to properly configure the application and what happens when more than two devices try to establish
connections:

Video showing the limitations


It is not indispensable to be an expert to realise that sharing USB-connected devices over networks cannot be
achieved without the execution of code in kernel mode. So, by having a look in the Windows\System32\Drivers folder
and ordering files by the Date Modified field, it is possible to see that three drivers, whose names are shown below,
were added during the installation of this software:

Image 04

Additionally, a Windows service was installed as well. By following the same steps but searching Windows\System32
for new files, this service is revealed:

Image 05

There is no doubt that one of them is responsible for protecting UOE, and because code in Ring0 should be executed
as much clearly as possible, the service named as usboesrv.exe is likely to play a key role in shielding the application.

Fortunately, not all of the endeavours to reverse engineer UOE by manipulating the main application were for nothing,
and valuable information has been obtained from that, which is used in this tutorial to finally break the service
protections. So, let's start with that approach to understand how the protection is working.

Nag Screen (exhaustive analysis)


After loading UOE in Olly and searching for All intermodular calls, an interesting reference to
CreateDialogIndirectParamA is found:
Image 06

To verify if this is the call that creates the NAG Screen, a breakpoint can be set at 0x42E833 to see what the effects
are when running the application. Indeed, after pressing F9 the debugger stops at that memory address, which is a
prosperous beginning.

By continuing debugging until the RET instruction at 0x42E8E0, the execution returns to 0x42EA62, just below the call
supposed to create the Nag Screen.
Image 07

Which could it be a way to deduce that this call is the one that really creates the Nag Dialog Box? By having a deep
look at the source above and setting a breakpoint at the memory address 0x42E9DE, it is possible to determine the
value of the RT_DIALOG-type resource, which is loaded from the resources. As the image below depicts, this value is
0x79:

Image 08

The use of the well-known Resource Hacker is the most direct method to determine whether or not the nag screen is
created here, and by accessing the resource 121 (0x79) located in the Dialog folder, it cannot be argued that rail has
been put on the right track:
Image 09

So, now that there is evidence that the call at 0x42EA62 is responsible for creating the dialog that reminds us how
many days left for evaluation, the temptation to find a workaround that cancels this call is huge. However, this is not
so simple like filling with NOP instructions the bytes representing the call, since all the code shown in the Image 07, is
related to the same thing: The Nag Screen. For instance, by debugging far from that call and reaching the address
0x42EA86, it can be seen that the dialog box already created is finally shown when executing the call at 0x42EA81:

0042EA7D . 5B POP EBX


0042EA7E > 53 PUSH EBX ; /Arg1
0042EA7F . 8BCE MOV ECX,ESI ; |
0042EA81 . E8 29290000 CALL usboe.004313AF ; \usboe.004313AF
0042EA86 > 397E 1C CMP DWORD PTR DS:[ESI+1C],EDI
0042EA89 . 74 2D JE SHORT usboe.0042EAB8

To sum up, the most convenient solution is NOT to make any change in the whole procedure and continuing tracking
back to find the right place where it is indeed determined if UOE is running as trial or not.

Based on that, the end the procedure at the address 0x42EB04 should be debugged to determine where that call
comes from:

0042EAF9 . 5F POP EDI


0042EAFA . 5E POP ESI
0042EAFB . 64:890D 00000000 MOV DWORD PTR FS:[0],ECX
0042EB02 . 5B POP EBX
0042EB03 . C9 LEAVE
0042EB04 . C3 RETN

Thus, the piece of code reached is a really interesting asset:


Image 10

The remarkable thing is not exactly the comparison of EAX with 0x66, but the other two ones just before the call at
0x4163C3 (which is essentially the call that creates and shows the nag screen) and the respective jumps associated
with them. These other two comparisons are:

00416380 > F68424 BC020000 80 TEST BYTE PTR SS:[ESP+2BC],80


00416388 . 0F85 AA020000 JNZ usboe.00416638
0041638E . 6A 00 PUSH 0
00416390 . 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20]
00416394 . E8 B7400000 CALL usboe.0041A450
00416399 . 8B8424 C0020000 MOV EAX,DWORD PTR SS:[ESP+2C0]
004163A0 . BB 0C000000 MOV EBX,0C
004163A5 . 83F8 0F CMP EAX,0F
004163A8 . 899C24 DC050000 MOV DWORD PTR SS:[ESP+5DC],EBX
004163AF . 0F8F 78010000 JG usboe.0041652D
004163B5 . 50 PUSH EAX
004163B6 . 8D4C24 20 LEA ECX,DWORD PTR SS:[ESP+20]
004163BA . E8 E1440000 CALL usboe.0041A8A0
004163BF . 8D4C24 1C LEA ECX,DWORD PTR SS:[ESP+1C]
004163C3 E8 DD850100 CALL usboe.0042E9A5 //(I'm the NAG creator)
004163C8 . 83F8 66 CMP EAX,66

When taking any of the jumps highlighted in blue, the nag screen is totally dodged, so it is important to watch and
understand the content of the addresses [ESP+2BC] and [ESP+2C0] . In order to do so, Olly is restarted and a
breakpoint set specifically at 0x416380 to visualise the memory content. Once again, UOE must be run and when Olly
stops, the value stored just exactly at ESP+2BC can be verified in the DUMP:
Image 11

IMPORTANT: From now on, some memory addresses might differ from what the readers obtain in their computers. As a
consequence, the new addresses have to be used to continue with this tutorial.

At this point, ESP+2BC is 0x12FBF0, and by experimenting with the values located from there on, it is feasible to work
out how they affect the execution of UOE. Just for now, concentrate on the first two DWORDS:

12FBF0 30 00 00 00 0B 00 00 00

What exactly 0x30 represents is not being treated in this tutorial, but it is known that if this value was 0x80 instead,
the nag screen would not appear. Additionally and according to the first image (Image 01), 11 days remain for
evaluation and that number is precisely the first byte of the second DWORD: 0x0B. To be completely sure that this
number affects the number of trial days left, it can be modified and the F9 key pressed to continue the execution. Let's
set 0x01 instead of 0xB0:

12FBF0 30 00 00 00 0100 00 00

As suspected, after pressing F9 key the number of days shown in the nag screen has changed:

Image 12

This basically indicates that those values can potentially lead to crucial parts of code that are sensitive. However, as it
was previously mentioned, by modifying them ONLY in the main process memory, UOE is launched but without
eliminating the main limitation: no more than two devices connected simultaneously.

As a consequence, it is likely to think what exactly the point of eliminating the nag screen is. Actually, doing so just
take readers to the right information and its respective format to look for into the Windows service memory.

Looking into the Windows service (usboesrv.exe)


Let's put aside the main executable file and concentrate on the service. Having knowledge that the values located at
0x12FBF0 do not affect the UOE's functionality, but only the appearance, it is beyond doubt that those values are
used somewhere else to have an impact on how UOE operates.

Owing to the fact that UOE features a service that interacts with the drivers, it is highly possible that the values
recently found come from it. So, let's see if they are located into the service memory space. In order to do so, quit the
main application, run Olly and attach the service usboesrv.exe, which is automatically executed at the Windows
startup:

Image 13

Once the service is fully attached and running, everything is ready to seek these crucial values out as it is shown
below (0x0A must be replaced with the number of days remaining on readers' computer):

Image 14

Likely, they can be found as presumed into the service memory space, more specifically at 0x6944A8.
Image 15

The memory address mentioned above is really important and might vary on other computers, so it is important that
readers keep it in mind.

Setting a value equal to 0x80 at 0x6944A8 should implies that the nag screen does not appear when running UOE. As
a matter of fact, by setting 0x80 and running the main application, desirable results can be achieved:

Image 16

Just exactly as it was thought, this is the way to get rid of the nag screen. Note that this time the values have been
modified on the service side, which mainly means that:

"It is the service which passes those values to the main application, but not vice versa, and that is exactly why it is
necessary to focus attention on it rather than the main application (usboe.exe)."

In order to reverse UOE, it is not actually mandatory to understand and/or describe how these values are passed, but
the aim of my tutorials have always been to show or teach something new that I have not dealt with in previous
essays (not necessarily other crackers). So before continuing, there will be a brief description of this technique utilised
for communication. Quit the application but let Olly running so as not to kill the service which is attached.
Named Pipes - A way of communication
A named pipe is a named, one-way or duplex pipe for communication between the pipe server and one or more pipe
clients. All instances of a named pipe share the same pipe name, but each instance has its own buffers and handles,
and provides a separate conduit for client/server communication. The use of instances enables multiple pipe clients to
use the same named pipe simultaneously.

Any process can access named pipes, subject to security checks, making named pipes an easy form of communication
between related or unrelated processes. Any process can act as both a server and a client, making peer-to-peer
communication possible. The term pipe server refers to a process that creates a named pipe, and the term pipe client
refers to a process that connects to an instance of a named pipe. The server-side function for instantiating a named
pipe is CreateNamedPipe. The server-side function for accepting a connection is ConnectNamedPipe. A client process
connects to a named pipe by using the CreateFile or CallNamedPipe function.

Named pipes can be used to provide communication between processes on the same computer or between processes
on different computers across a network.

Finally, since both usboe.exe and usboesrv.exe are processes, the communication between them is established by
pipes and that is exactly how the services sends or shares information with the application. In order to do so, there
are specific Named Pipe Operations.

These operations will not be described in details in this tutorial, but it is worthwhile to explain that as soon as the
pipe server creates a pipe instance, a pipe client can connect to it by calling the CreateFile or CallNamedPipe function.

Once the connection is established, pipe clients and servers can call one of several functions to read from and write to
a named pipe. The behavior of these functions depends on the type of pipe and the modes in effect for the specified
pipe handle, as follows:

The ReadFile and WriteFile functions can be used with either byte-type or message-type pipes.

The ReadFileEx and WriteFileEx functions can be used with either byte-type or message-type pipes if the pipe
handle was opened for overlapped operations.

The PeekNamedPipe function can be used to read without removing the contents of either a byte-type pipe or a
message-type pipe. PeekNamedPipe can also return additional information about the pipe instance.

The TransactNamedPipe function can be used with message-type duplex pipes if the pipe handle to the calling
process is set to message-read mode. The function writes a request message and reads a reply message in a
single operation, enhancing network performance.

When a client and server finish using a pipe instance, the server should first call the FlushFileBuffers function, to
ensure that all bytes or messages written to the pipe are read by the client. FlushFileBuffers does not return until the
client has read all data from the pipe. The server then calls the DisconnectNamedPipe function to close the connection
to the pipe client. This function makes the client's handle invalid, if it has not already been closed. Any unread data in
the pipe is discarded. After the client is disconnected, the server calls the CloseHandle function to close its handle to
the pipe instance. Alternatively, the server can use ConnectNamedPipe to enable a new client to connect to this
instance of the pipe.

Remarks
Typically the WriteFile and WriteFileEx functions write data to an internal buffer that the operating system writes to a
disk or communication pipe on a regular basis. The FlushFileBuffers function writes all the buffered information for a
specified file to the device or pipe.

UOE Named Pipe Scheme


Now that the named pipes functionality has been described to understand how data is shared between different
process, it is good idea to see how this scheme is working for USB Over Ethernet:

Named pipe scheme for UOE

PIPE_ACCESS_DUPLEX: The pipe is bi-directional; both server and client processes can read from and write to the
pipe. This mode gives the server the equivalent of GENERIC_READ and GENERIC_WRITE access to the pipe. The client
can specify GENERIC_READ or GENERIC_WRITE, or both, when it connects to the pipe using the CreateFile function.

FILE_FLAG_OVERLAPPED: Overlapped mode is enabled. If this mode is enabled, functions performing read, write, and
connect operations that may take a significant time to be completed can return immediately. This mode enables the
thread that started the operation to perform other operations while the time-consuming operation executes in the
background. For example, in overlapped mode, a thread can handle simultaneous input and output (I/O) operations
on multiple instances of a pipe or perform simultaneous read and write operations on the same pipe handle. If
overlapped mode is not enabled, functions performing read, write, and connect operations on the pipe handle do not
return until the operation is finished.

For those who closed Olly and accidentally killed the service, it is indispensable to execute and attach it to Olly again
before continuing. In order to do so without restarting the operating system, the Windows Service Manager can be
used:

Image 17

Once the service manager is running, the service associated to UOE can be found:

Image 18
A double click on it shows the property windows and exactly from there, the service can be started or stopped. If the
service is already stopped, it must be started again:

Image 19

Once the service is running and attached to Olly, let's set a Hardware on Access Breakpoint at 0x6944A8, the address
containing the byte that determines the application's status: trial or not.

Image 20

Once the main application is executed, it is stopped at 0x4120EF because the instruction MOV EDX, DWORD PTR DS:
[ECX+58], which has just copied 0x00000080 to EDX (or 0x00000030 if the service was re-started without being
patched). Press once F8 key to copy 0x00000080 to 0x99FEDC which is the value in EAX:

Image 21

and set a new breakpoint at WriteFile: BP WriteFile. Press F9 to let UOE run again and the execution will stop at the
beginning of WriteFile, showing this marvelous information on the stack:

Image 22

The image above clearly shows the address of the buffer that the writing operation is using, which is 0x99FEDC, just
exactly where 0x00000080 is. It does not denote that some bytes are just about to be written at this memory
address, but the bytes at that address are going to be written to other place. Where exactly? According to the Named
Pipe theoretic content previously exposed, those bytes are being written to the client or main application (usboe.exe).
That is exactly how data is passed between client and server.

Now that the communication between the service and the client has been explained, it is necessary to think about a
way to reverse UOE.

Revealing the protections


The trickiest parts of reversing UOE have just begun owing to the unexpected protections that are mandatory to deal
with.

It has been seen that the service and what it does, it is what really matters. So, it is obvious that the service must be
patched to make the application work as registered. Previously, some patches were made in the service memory
space when attaching it to Olly for analysis purposes, but now, the service must be patched on disk to make the
modifications remain permanently and here is when the problems begin.

The service side (usboesrv.exe) is already packed with UPX, but of course it does not actually represent any drawback
since there are automatic tools that can easily unpack it. Even the manual unpacking of UPX cannot take more than
one minute. UPX is a packer rather than a protector and there is enough information on the Internet about it, so,
unpacking UPX is not treated in this tutorial. For those reader who have no experience in unpacking UPX manually, I
would recommend some automatic tools like GUiPeX, PE-Explorer, for instance.

Before unpacking usboesrv.exe, the service must be stopped as it was previously described. Once unpacked, its size
is expanded up to 464KB approximately, depending on the unpacking technique used, and the service can be re-
started. There is not even necessary to patch its memory to see how the unpacking has affected its execution. Just
double click on the application icon and UOE cannot be initialized:
Image 23

After a while, the related message box emerges:

Image 24

What is more, by modifying just a single byte of the original packed service (without unpacking) the results would be
the same, for instance, by replacing the last byte in the packed service:

Image25

or even by replacing an insignificant byte of the header:

Image 26

As a result, there is no doubt about the presence of some sort of CRC, HASH, Checksum or Digital Signature protecting
UOE from crackers.

To make things worse, there is an extra handicap to tackle and this tutorial is now moving towards its direction. Make
sure the original version of the service is running and attached to Olly, and set again a Hardware on Access
Breakpoint at 0x6944A8 (it was formerly showed how to find this address which might be different depending on the
computer). When the main application is executed, Olly stops at 0x4120EF just exactly as the Image 20 shows above.

There is nothing new here, but when F9 key is pressed again to let the application run, the second obstacle is
uncovered: ENCRYPTION. Once the application is launched, go back to 0x4120EF to appreciate how the set of
instructions shown in the Image 20 have completely changed:

Image 27

The image above essentially reveals that the sensitive parts of code are decrypted, executed and then encrypted
again for security reasons. "A Sensitive part" primarily means that a portion of code which has to be patched to get a
functional version of UOE, is encrypted...

Analysing the CRC/HASH/Checksum/Digital Signature


It can be easily deduced from what was recently exposed above that it is the service itself which verifies its integrity
without depending on the main application. Let's compare the values starting at 0x6944A8 for both the original and
patched service:

Original Service:

Image 28

Original Patched or unpacked Service:

Image 29a

When the service detects that it has been modified by using some Cheksum, CRC, HASH, whatever it is, the number of
remaining days is set to 0x00, and it can be plainly perceived if comparing Image 28 with Image 29a at the address
0x6944AC. Note that in order to do so, two different versions of the service have been run and attached to Olly one
by one, while the main application has not played any role.

QUESTION: How do the developers know the final and correct CRC or HASH value at development time priory to
compilation and even priory to pack the service with UPX?

The answer is that they do not know it AT THE SERVICE DEVELOPMENT STAGE, but it is doubtless that they are using
some technique to calculate and store it somewhere once the service is packed. Some different hypothesis about how
they do this might be:
Hypothesis 1: According to the UPX documentation, the packer internally maintains a checksum of both the
compressed and uncompressed files. As a consequence and owing to the fact that UPX is a free-distributed
application that includes the source code, the developers of UOE could have done some research looking into the
source code in order to understand how to calculate the cheksum once the file is compressed.

Hypothesis 2: A CRC, HASH or Checksum is applied to the compiled/packed version by using an external tool and the
result is stored in the executable file, at a specific offset that does not affect the decompression and which is not
considered when the application calculates its own CRC/HASH.

Hypothesis 3: Once the service is compiled, it could be signed digitally by using a private key, and then the signature
stored as an array of X bytes in one of the drivers that UOE features. Hence, when the services starts, it computes its
own hash which is later verified by using a combination of the public key and the signature held by a driver.

Hypothesis 4: A fusion of the methods 2 and 3. For instance, a simple Checksum/CRC/Hash (not a signature) stored in
the driver.

Of course, the possibilities are not limited to the four ones exposed above as these hypothesis are just an example.
What is more, Windows APIs like CryptImportKey, CryptCreateHash, CryptHashData and CryptVerifySignature are not
called from the service, so the third theory could be dismissed; although the developers could have implemented their
own functions to sign and verify software.

In any case, the unpacked version of the service has been analysed with Hash & Crypto Detector v1.4, an useful tool
to detect cryptographic marks, and the results obtained were promising:

Image 29b

The outcomes show that there is an indicator of a MD5 hash function at the 0x463C44 virtual address. Let's see what
there is at that location:
Image 29c

Although the entire block is 256 bytes long, it looks like a 128-bit hash value (first 16 bytes), especially because a
reference to this group of bytes has been found in the code at 0x44570C:

Image 29d

The procedure above also features several bit shift operations like SHR and SHL until its end, and this could be a clear
sign of an own-developed MD5 Hash function. What is more, this procedure is referenced four times along the service,
but the most interesting thing is the code found around one of these references:
Image 29e - Image 29f

That code has been also debugged at the service startup and it can be confirmed that its execution takes place
several times just before detecting if the service has been modified or not. Furthermore, it has been proven that the
SHR and SHL functions operate upon bytes taken from the service in order to perform calculations. Besides, the loop
between 0x445676 and 0x445690 depicts without any doubt how pointers are incremented by an hexadecimal value
of 0x40 (64 decimal), which is an imminent sign of MD5.

Consider that MD5 processes a variable-length message into a fixed-length output of 128 bits. The input message is
broken up into chunks of 512-bit blocks, which means that each block is 64 bytes long (exactly the same value used to
increment the pointers); then the message is padded so that its length is divisible by 512. The padding works as
follows: first a single bit, 1, is appended to the end of the message. This is followed by as many zeros as are required
to bring the length of the message up to 64 bits fewer than a multiple of 512. The remaining bits are filled up with a
64-bit integer representing the length of the original message, in bits.

Under such conditions, the presence of an own-developed (probably non-standard) MD5 algorithm can be confirmed
without hesitation.

Finally, to make this hypothesis irrefutable, the same 128-bit hash value MUST be ALSO found in the packed version of
the service (since this is a hash that was applied to the original packed version), or at least in one of the drivers.
Searching for them with an hexadecimal editor the existence of this hash in the original packed version cannot be
omitted:

usboesrv.exe (original packed version; 186Kb):


Image 29g

What is more, the whole block marked in blue in Image 29c entirely appears in Image 29g, and not only the first 16
bytes. There is just a slightly difference between the block in Image 29c and the one shown in Image 29g: the second
one is 0x20 bytes longer. This is owing to the fact that the bytes of this block are divided into groups of 0x20 bytes
separated by the DWORDS "FF FF FF FF" in between and "04 20 FF FF" at the end (Some sort of CRC at the end?).

Image 29h

Additionally, it is worthwhile to mention that the code that loads the file itself into memory and then compute the MD5
was in addition debugged. As a result, it was also detected that "during that process" a notorious number of direct
input and output operations were performed on at least 4 different devices by using the DeviceIoControl function. No
further research on that has been carried out for this essay. However, those suspicious I/O operations must be
considered when conducting a supplemental examination on the integrity self-verification process in order to
determine any driver intervention, which is almost a fact, since exactly the same MD5 cryptographic mark has been
also found in two of the drivers:

usboeloaderdrv.sys:
Image 29i

usboebusdrv.sys:

Image 29j

Owing to the complexity of this tutorial, an exhaustive analysis of the algorithm utilised for the self-verification of
integrity will be a topic to discuss in other essay.

Nevertheless, there is a trick that has always brought good results to bypass CRC/MD5 functions without necessarily
having knowledge of the algorithm. This is exactly the same trick that it was exposed on my tutorial about inline
patching of Asprotect.

The trick basically consist of intercepting the load of the bytes computed for the calculation of the
CRC/HASH/Checksum/DS into memory. At that point, when the patched or unpacked process points to its own image
on disk, the file name must be changed in order to make reference to the original file. So, the original bytes are loaded
into memory instead of the ones of the cracked version and the calculation of the CRC is successful.

It looks a slightly complex technique, especially in this case where the interception has to be done in a portion of code
which is encrypted, but it is going to be easier than dealing with the analysis of the input/output operations
performed on drivers.

Encryption
Before starting to look for the sensitive parts to patch, it is valuable to mention that every encrypted section of the
service "generally" has the following structure:
Encryption scheme for protected procedures featuring sensitive parts

In order to bypass encryption, the alternatives are:

1) Inline Patching: This technique implies to call a patching routine, which has to be located in an empty part of the
EXE file, just after a piece of code is decrypted and in order to patch it before being executed and encrypted again.
This approach has been successfully tried with UOE, but in the end, the second technique is part of this tutorial as this
first method was implemented in former essays.

2) Removing the encryption: This approach refers to dump the encrypted parts when they are decrypted as well as
removing the functions that decrypt and encrypt at the beginning and end of a section respectively. This will be the
approach described in this tutorial.

Having decided which technique to implement, it is now necessary to find which instructions of the service have to be
patched (previously, only data memory was patched from Olly).
Debugging a Windows service startup with Olly
Now, for those who are getting nervous because of so many difficulties, let me tell that it is necessary to face up an
extra one, although this is not a protection method, but an inherent issue in reversing services.

Unfortunately, the sensitive parts to find are executed at the service startup. So, attaching the service to Olly after
the execution of those pieces of code is completely useless and that is why the service must be attached at the
execution of its entry point which is called ServiceMain Callback Function.

There are several methods describing how to debug Windows services at the Microsoft website, but none of them has
been put into practice for this tutorial. Besides, neither WinDbg nor VMWare are installed at this moment on the
computer where the essay is taking place and the edition of values in the Registry does not seem to be an appealing
method.

As a consequence, I am going to show my own method using Olly. I cannot precise whether or not this procedure was
implemented before by other crackers since I have no time to read tutorials, but whatever the case is, I hope you
enjoy it.

In order to understand why the ServiceMain Callback Function is the desired entry point to start debugging, it is
recommended to read first some theory of Windows service functions.

StartServiceCtrlDispatcher Function
Connects the main thread of a service process to the service control manager, which causes the thread to be the
service control dispatcher thread for the calling process.

Syntax

BOOL WINAPI StartServiceCtrlDispatcher


(
__in const SERVICE_TABLE_ENTRY *lpServiceTable
);

Parameters

lpServiceTable [in]

A pointer to an array of SERVICE_TABLE_ENTRY structures containing one


entry for each service that can execute in the calling process. The
members of the last entry in the table must have NULL values to designate
the end of the table.

SERVICE_TABLE_ENTRY Structure
Specifies the ServiceMain function for a service that can run in the calling process. It is used by the
StartServiceCtrlDispatcher function.

Syntax

typedef struct _SERVICE_TABLE_ENTRY


{
LPTSTR lpServiceName;
LPSERVICE_MAIN_FUNCTION lpServiceProc;
} SERVICE_TABLE_ENTRY, *LPSERVICE_TABLE_ENTRY;

Members

lpServiceName

The name of a service to be run in this service process.

If the service is installed with the SERVICE_WIN32_OWN_PROCESS service


type, this member is ignored, but cannot be NULL. This member can be
an empty string (""). If the service is installed with the
SERVICE_WIN32_SHARE_PROCESS
service type, this member specifies the name of the service that uses
the ServiceMain function pointed to by the lpServiceProc member.

lpServiceProc

A pointer to a ServiceMain function.

RegisterServiceCtrlHandler Function
Registers a function to handle service control requests.

This function has been superseded by the RegisterServiceCtrlHandlerEx function. A service can use either function, but
the new function supports user-defined context data, and the new handler function supports additional extended
control codes.

Syntax

SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandler


(
__in LPCTSTR lpServiceName,
__in LPHANDLER_FUNCTION lpHandlerProc
);

Parameters

lpServiceName [in]

The name of the service run by the calling thread. This is the service
name that the service control program specified in the CreateService
function when creating the service.

If the service type is SERVICE_WIN32_OWN_PROCESS, the function does not


verify that the specified name is valid, because there is only one
registered service in the process.
registered service in the process.

lpHandlerProc [in]

A pointer to the handler function to be registere.

Remarks

The ServiceMain function of a new service should immediately call the RegisterServiceCtrlHandler function to
register a control handler function with the control dispatcher. This enables the control dispatcher to invoke the
specified function when it receives control requests for this service. For a list of possible control codes, see Handler .
The threads of the calling process can use the service status handle returned by this function to identify the service in
subsequent calls to the SetServiceStatus function.

------------------------

It is pivotal to differentiate between ServiceMain and the main thread of a service: When the service control manager
starts a service process, it waits for the process to call the StartServiceCtrlDispatcher function. The main thread of a
service process should make this call as soon as possible after it starts up (within 30 seconds). If it fails to do so, it
will be impossible to connect the main thread of a service process to the service control manager, which implies that
the service will not be started and cannot be debugged.

However, if the service process is completely started, the sensitive parts have been missed for debugging. As a
consequence, it is necessary to find a point where stopping the execution does not affect the critical 30 seconds but
also does not prevent us from debugging the sensitive parts.

According to what has been exposed above, that point is exactly the BEGINING OF THE ServiceMain Function, which
has been called the Saccopharynx's Service Ripper Point.

When the service control manager receives a request to start a service, it starts the service process (if it is not
already running). The main thread of the service process calls the StartServiceCtrlDispatcher function with a pointer to
an array of SERVICE_TABLE_ENTRY structures. Then the service control manager sends a start request to the service
control dispatcher for this service process. The service control dispatcher creates a new thread to execute the
ServiceMain function of the service being started, and because this ServiceMain function is executed in a different
thread, stopping its execution at the beginning does not prevent StartServiceCtrlDispatcher from connecting the
main thread to the service control manager within 30 seconds.

Thus, the Service Control Manager does not terminate the process that hosts the service. In the contrary, the Service
Control Manager would end the process and the attached debugger while debugging.

Additionally, the ServiceMain function is which has to contain any service-specific initialization, such us the sensitive
parts, and since it is stopped at the beginning, none of those parts will be skipped.

Saccopharynx's Service Ripper Point (SSR Point)


Before continuing, it is recommend stopping the service in order to start working with the unpacked version. If it was
unpacked manually, make sure that it was dumped properly and its OEP and IAT have been fixed as well. For those
readers who did not unpack the service, it is now time to do so or use the unpacked version included with this
tutorial: (usboesrvUnpacked.exe).

Make a copy of the original service and rename it as usboesro.exe. Additionally, rename the unpacked version as the
original name of the service: usboesrv.exe. Just like this:

usboesrv.exe -> usboesro.exe

usboesrvUnpacked.exe -> usboesrv.exe

The service must be now restarted to start working with the unpacked version. As the service is just about to be
patched, the main application cannot be launched yet.

Actually, the SSR Point is not difficult to be found since this is the beginning of the ServiceMain function, and it does
not even take long to do so. According to the fundamentals exposed above, a pointer to the ServiceMain is the
second field of the _SERVICE_TABLE_ENTRY structure, and a pointer to this structure is the parameter passed to
StartServiceCtrlDispatcher.

In order to locate the SSR Point, the service has to be attached to Olly to look for a StartServiceCtrlDispatcher
reference. Searching for all intermodular calls lead us to it:
Image 30

Following the address where the call is performed can help to find the SSR Point:

Image 31

The Image 31 shows that EDX holds the pointer to the _SERVICE_TABLE_ENTRY structure, which is exactly the value
at EBP-2C (see the instruction at 0x44B168 followed by the PUSH EDX). Thus, the value at this memory address is the
first parameter of the structure, so the value located at EBP-28 must be the second parameter, and that is exactly
what has to be tracked down. The instruction at 0x44B16F clearly shows that 0x44AD70 is the SRR Point as this value
is stored at EBP-28.

A different approach to find this value would be looking for a reference to RegisterServiceCtrlHandler by searching for
all intermodular calls:

Image 32

It is known that he ServiceMain Function is responsible for calling RegisterServiceCtrlHandler, so let's see what can be
obtained at 0x44B2B3:
Image 33

Unfortunately, there is nothing interesting between 0x44B2A0 and 0x44B300 apart from the call to
RegisterServiceCtrlHandler. It basically indicates that the ServiceMain is calling this function to register a function to
handle service control requests, so in order to get the ServiceMain it is necessary to find references to 0x44B2A0. Go
to 0x44B2A0 and press CTRL+R to find the only reference to the code above:

Image 34

As it was expected, this call is performed inside the ServiceMain function, and not surprisingly, the location where this
function begins is 0x44AD70; the same one previously found through the former method:

Image 35

The aim of this section is to prepare the unpacked version to start debugging the service at its startup so as not to
miss the initializations that determine how UOE will be executed: trial or not. As it was earlier mentioned, the service
must be stopped at the SSR Point, and in order to do so, an infinite loop must be set at 0x44AD70:
Image 36

Now mark the modified code entirely an select the Copy to executable -> Selection option and save the file as
usboesrvPatched1.exe. Once the changes have been saved, stop the service and rename the files as follows (in the
same order):

usboesrv.exe -> usboesrvUnpacked.exe

usboesrvPatched1.exe -> usboesrv.exe

Finally, start the service again to experience how long it really takes to get initialized; much more than 30 seconds. Of
course, it is owing to the infinite loop already set at the SSR Point:

Image 37

After a couple of minutes, the following message appears although it does not represent any inconvenient:

Image 38

It is not even necessary to wait for this message box, so when it appears, just press Ok an continue the reversing.

Many readers could ask how it is supposed to continue if the service was not started...

According to the basic principles of Windows Services, the service must be started within 30 seconds to connect the
main thread of a service process to the service control manager. In the contrary, the service will not be started and
cannot be debugged.

Well, the thing is the service was started indeed, but because of the infinite loop, the control handler function of the
service was not yet registered with the control dispatcher, so it is still disable to invoke the specified function when it
receives control requests for this service. In a few words, it occurs because of the infinite loop preventing the
ServiceMain function from calling the RegisterServiceCtrlHandler function.

Have a careful look at the message and what it really says: "...The service did not respond to the start OR CONTROL
REQUEST in a timely fashion..."

As a consequence, what really happened here is that the service responded to the start but NOT TO THE CONTROL
REQUEST, and that is exactly why the service has not been stopped and unloaded from memory. Finally, after
pressing the Ok button and having a look at the service manager, it can be appreciated how the service cannot be
started or stopped either, since it is status is STARTING:

Image 39

When it happens and it is also necessary to stop the service for any reason, there are two alternative ways:

1) Use the Task Manager.

2) Attach it to Olly and then close the debugger.

After doing so, the service can be restarted again.

Crack the Riddle


Just to make clear what the aim of this section is, the main tasks are mentioned in brief:

1) Search for the CRC/HASH/Checksum/DS Verification


and patch it.

2) Look for a sustainable way to remove the limitation upon


the number of devices to connect and the number of days left
for evaluation.
As it was previously disclosed, these sensitive parts where the service has to be patched, are encrypted and the
strategy will be to remove the encryption permanently.

1) CRC/HASH/Checksum/DS Verification
This is the first protection to kill since as soon as the service detects it has been modified, a proper initialization does
not take place and the code executed might not be the same. This could basically moves us far away from the code to
be patched so as to remove the other limitations.

In order to continue, make sure that usboesrvPatched1.exe has been renamed as usboesrv.exe and subsequently
stared and attached to Olly. It is also necessary to keep a copy of the original file renamed as usboesro.exe in the
same folder.

To bypass the Checksum, it is necessary to seice the load of bytes into memory in order to change the name of the file
that is used as source. Thus, a file name like C:\WINDOWS\system32\usboesrv.exe will be turned into
C:\WINDOWS\system32\usboesro.exe.

There are several methods to use so as to load a file into memory, but it was decided to start with the
GetModuleFileNameA function. Fortunately, the right trail has been taken as this is the API function used for UOE to
return the service file name into its own memory addresses space. The following steps can be followed to get the first
sensitive part to patch:

1) Set a BP GetModuleFileNameA

2) Go to the SSR Point (0x44AD70) and before restoring the


original instructions, toggle a breakpoint on (F2) at an
address a few instructions below; at 0x44AF7A for
instance. This breakpoint is necessary just to avoid
unexpected exceptions when releasing the execution that
for some reason sometimes fails if no breakpoint is set.
So, verify you have set a configuration similar to the
one below:

Image 40

3) Restore the original instructions as it is shown


above: SUB ESP,1C

4) Release the execution (F9)

5) When the execution is stopped at 0x44AD7A, press


F9 one more time.
Image 41

After releasing the execution at the address shown above, the debugger stops exactly at the beginning of
GetModuleFileNameA. Surprisingly, this call comes from 0x40E161:

Image 42

This is surprising because there is not any call at that address when the service execution starts, so this is an
indicator of encryption. Follow in Dump the address 0x89F800 which is the location of the PathBuffer, buffer that will
contain the file name when returning from the API function. Now, press ALT+F9 to return from the call and see where
exactly the execution continues:

Image 43

At that point, the buffer contains: C:\WINDOWS\system32\usboesrv.exe and it is necessary to find a way to change
its content after the execution of GetModuleFileNameA, in order to get something similar to what the Image 44
depicts:

Image 44

Before doing so, it is important to understand that this patch MUST be done when these instructions are decrypted,
since they are still encrypted at the beginning of the execution:
Image 45

Compare both pictures Image 43 and Image 45 and appreciate the difference:

Image 43: -> Code is decrypted


Image 45: -> Code is encrypted

The conditional jump at 0x40E169 is taken when GetModuleFileNameA does not return an error; so considering that
such error should not occur as long as other application has not opened the service exclusively, the code can be
modified just after the call:

Image 46

According to the image above, it is needless to say that when no errors occur, the execution goes directly to the code
that calls CreateFileA in order to open the file whose name is in the buffer, and the new instructions in red modify the
PathBuffer in order to change the file to read:

40E167 MOV BYTE PTR DS:[EAX+EBP-17D], 6F


This instruction copies the character 0x6F ('o') so as to
replace 0x76 ('v') in the PathBuffer. Thus, UOE is actually
reading the copy of the original packed service.
The calculation [EAX+EBP-17D] comes from both the
instruction at 0x40E158, which loads the starting address
of the PathBuffer in EDX, and from the value returned
of the PathBuffer in EDX, and from the value returned
by GetModuleFileNameA in EAX, which is the length of the
string copied to the buffer. Hence, it is easy to see that
[EAX+EBP-178] would point to the end of the string instead
of to the character 'v', and that it is why it is necessary
to create a pointer that points to the 5th byte before the
end of the string: [EAX+EBP-178-5] = [EAX+EBP-17D]

40E16F JMP SHORT 0x40E1DC


It is assumed that there is no error and a jump is directly
taken to 0x40E1DC, the same as the original code does.

To make these changes remain as permanent, the encryption must be removed. The two images below show part of
the encryption scheme mentioned at the end of the section named as "Reveling the Protections". Image 47 depicts
the code when it is encrypted while Image 48 shows the opposite. The piece of code in blue, which is exactly the
same for both snapshots, decrypts the code from 0x40E0FB on:
Image 47 - Image 48

It is up to the readers to debug the decrypting code above to understand how it exactly works, but in brief, it is the
call at 0x40E0CF which finally decrypts the whole code and if no errors were found, the execution continues normally
towards the decrypted code:

40E0CF CALL EAX ;it decrypts the code between


;the range 0x40E0FB - 0x40E468
40E0D1 TEST EAX, EAX
40E0D3 JE 40E48B ;if error, get out of here. It directly
;jumps to the end of the function
40E0D9 JMP 40E0FB ;No error found, let's load the file into
;memory
The encryption code can be found at the end of the procedure and it is marked in blue below. This code encrypts
again the address range 0x40E0FB - 0x40E468 for security reasons:

Image 49

Once the right instructions has been patched and the pieces of code that deal with the encryption identified, it is
necessary to fill them with NOP instructions in order to avoid the overwriting of our patch in memory.

For decryption: Fill with NOP instructions the address range 0x40E0BA - 0x40E0FA

For encryption: Fill with NOP instructions the address range 0x40E457 - 0x40E4A6. Note that this portion of code
includes the red zone marked in the picture labeled as Image 49 despite the fact that it is originally encrypted.
However, because of the relative jump at 0x40E45B, which directly goes to the encryption instructions, it could be
convenient to remove the code in red as well. The patch seems to work, but it could even have no affect at all and it is
up to the reader to investigate what it really does.

Finally, when the code it is totally modified, which includes Decryption, PathFile, and Encryption patches, it is time to
make these changes permanent by saving the modifications into a new file. In order to do so, please follow these few
steps:

A) Mark the address range 0x40E0BA - 0x40E4AA

B) Select Copy to executable -> selection by


right-clicking the marked code.

C) In the new window select Save file

D) Choose usboesrvPatched2.exe as the new name.

E) Rename your files as follows:

usboesrv.exe -> usboesrvPatched1.exe


usboesrvPatched2.exe -> usboesrv.exe

F) Close Olly and the service will be stopped.

G) Restart the service again to continue with the


patching of other sensitive parts.
2) Removing the limitations
In this section it will be described how to patch the service to definitely eliminate the Nag Screen and two limitations:
the number of days left and the number of devices that can establish connection. Once upon at the beginning of this
tutorial, the values that directly affect the limitations were determined in the service memory space:

It was also mentioned that the first two DWORD respectively indicate:

6944A8 if DWORD == 30 00 00 00 -> Show the nag screen


if DWORD == 80 00 00 00 -> Don't show the nag screen

6944AC -> The number of days remaining. In this case, 0x0A


(This number must be always greater than zero)

Additionally, it is also needed to find which value determines the maximum number of devices connected
simultaneously. Since the trial version does not allow to connect to more than 2 devices, it is highly possible that the
byte or dword located at 0x6944B8 represents that value, as it is 0x00000002. Well, the service has been debugged
and what was mentioned in this paragraph can be confirmed.

Finally, the DWORD located at 0x6944BC , in this case 0x00000001, indicates the number of licenses. It was not
precisely determined what this value is used for, since according to the website, it is possible to buy a single license
for 2, 3, 4, 5, 6 or even unlimited connections. It means that the number of devices that can be connected does not
depend on the number of licenses purchased. So, it might be just an informative value used to show the type of
intalled licenses when selecting Help/About from the menu. Hence, this value will not be modified and the second
limitation is determined by the value at 0x6944BC.

6944BC -> The maximum number of devices allowed to


establish connection
(It will be later set to 0x0A. No special reason...)

In order to continue, the service must be already restarted and attached to Olly. Furthermore, the following
breakpoints have to be set to exactly detect when, and where, the memory addresses mentioned above are written:

Hardware Breakpoints on Write byte at:


0x6944A8 (Nag Screen)
0x6944AC (Days remaining)
0x6944BC (Number of Devices)

Memory Breakpoint on Write at:


0x6944A8 (Reason descrtibed below)

The aim of the Memory Breakpoint is to make Olly stop when any of the addresses listed above are written. For some
particular reason, Olly does not stop sometimes if this breakpoint is not set. Hence, the Olly HBP configuration should
look similar to the following image:
Image 49b

When all these breakpoints are set, follow the steps 2 to 5 described at the beginning of this section; the same ones
that were used to find the first sensitive part.

After releasing the execution at 0x44AD7A, the debugger stops exactly where the Image 50 shows below:

Image 50

The instruction that really makes Olly stop is:

0040BF54 MOV DWORD PTR DS:[EAX+5C], 0

This instruction basically moves 0x00 to 0x6944AC, which means that it writes the number of days. This is interesting
because after debugging the service a couple of times, it was discovered that this instruction is ALWAYS executed
regardless the number of days remaining.

QUESTION: Why is UOE writing 0x00 when there are still remaining days? At first, this writing operation was supposed
to be some sort of initialization, but then it was determined that it is not indeed. This application works as described
below:

If the trial period has not expired, 0x00 is later overwritten by the real number of days remaining. However, if the trial
period has finished, 0x00 will not be overwritten and this basically indicates to UOE that no device is allowed to
establish connection, even if the rest of patches are successfully done. That is exactly why it must be patched.

Before patching this, it has to be considered that the instruction is located in a sensitive part, which essentially means
that this instructions are originally encrypted. In order to check this, usboesrvPatched1.exe can be opened with
another instance of Olly. Just open it without executing code and go to 0x40BF5A:
Image 51

Now by comparing Image 50 with Image 51, there is no doubt that encryption was used to protect this code as well.
So, the same procedures have to be repeated.

Image 52 - Image 53
The code marked in blue in the images above puts on show the routine that decrypts the instructions from 0x40BEDC
on. Image 52 also depicts the patch that has to be performed in order to set a value different from 0x00 for the
number of days remaining. Once again, it is up to the readers to debug the decryption routine, but it is almost similar
to the first one found when patching the PathBuffer.

The encryption code can be found at the end of this very large procedure and it is marked in blue below. This code let
the address range 0x40BEDC - 0x40DC41 encrypted again for security reasons:

Image 54

Once both the encryption and decryption parts have been identified, they must be filled with NOP instructions BEFORE
continuing searching for the rest of the places which are necessary to patch. This time, all of the modifications
remaining will be saved together at the end of the tutorial when there are no more patches to apply.

Now, it is not even required to set more breakpoints, so press F9 key to continue searching for more sensitive parts.
Then, the debugger stops at 0x40C25F as a consequence of the previous writing instruction:
Image 55

As it can be clearly seen, the instructions above are still located in the same procedure where the last patch was done
(between 0x40BEDC and 0x40DC41) . This indicates that no extra encryption/decryption routines have to fill with NOP
instructions this time, as they are already patched.

The following instruction writes the number of devices allowed to establish connection at EAX+68. Here, EAX+68
points directly to the third HBP set earlier (see Image 49b):

0040C25C MOV DWORD PTR DS:[EAX+68], EDX

As it was formerly mentioned, 0x0A is set for no special reasons and just because ten devices represent a large
number of devices to share simultaneously. A possible patch to do so can be as follows:

Image 56

Press F9 one more time and the execution will stop at 0x40C26B as it is shown above. Here the content of EDX is
written at EAX+58 which is already pointing to 0x6944A8, just exactly where both the first HBP and the Memory
breakpoint are set. As stated, this value determines if the Nag Screen appears or not and it must be 0x80 to definitely
eliminate it. As a consequence, a possible patch could be:
Image 56b

Theoretically, all the necessary patches in the sensitive parts should have been already done since the values that
regulate the functionality of UOE have been written:

1) CRC/Hash/Checksum/DS Verification: Patch at 0x40E167

2) Number of days left: Patch at 0x40BF54

3) Maximum number of simultaneous devices connected:


Patch at 0x40C256

4) Nag Screen : Patch at 0x40C265

5) Decryption/Encryption routines. Nop instructions at:


Range: 0x40E0BA - 0x40E0FA (Decryption)
Range: 0x40E457 - 0x40E4A6 (Encryption)
Range: 0x40BE9B - 0x40BEDB (Decryption)
Range: 0x40DC47 - 0x40DCA7 (Encryption)

Now, it is recommended not stopping debugging the service or closing the debugger despite the fact that all of the
patches are supposedly done. Press F9 again to verify if the service starts or Olly continues stopping. Indeed, Olly will
stop at least one more time, just exactly at the address that the image below shows:

Image 57

The debugger has stopped at 0x40F97A as consequence of the instruction at 0x40F973, which writes AGAIN zero as
the value for the days left. Why again? Well, UOE has not calculated yet the number of days remaining and for
security reasons it might write 0x00 on more time, just to annul the effects of a possible patch made previously.
Before continuing, it is necessary to make exactly the same patch that the Image 53 depicts, by replacing 0x00 with
0x0F:
Image 58

Once again, this is an encrypted sensitive part and both the encryption and decryption routines must be filled with
NOP instructions at this point where the code is already decrypted. Below, the decryption routine is presented:

Image 59 - Image 60

The encryption routine at the end of the procedure is as follows:


Image 61

Now fill with NOPs the three-marked-in-blue pieces of code above.

Readers who did not get lost may ask where exactly the number of days is being written. Well, subject to the number
of days left on your computer, Olly might stop on more time, and that is exactly when the number of days remaining is
finally written. However, If the trial period for UOE has expired, that value is never written as the days remaining is 0
and that is exactly the value that UOE wrote at both 0x40BF54 and 0x40F973.

If F9 key is pressed one more time and the trial period is by now expired, the service is totally executed.
Nevertheless, if there are some days remaining, Olly stops as follows:

Image 62

Here EAX contains the number of days remaining for trial period and it is written to 0x6944AC. REMEMBER, the code
that Image 62 shows is ONLY executed if UOE can be still evaluated and that is why the instructions at 0x40BF54 and
0x40F973 were patched. This prevents the service from writing ZEROS at that memory address in case of expiration,
which essentially would lead to not to accept connections. In a few words, those patches ensure that there will
ALWAYS be remaining days. Thus, there is no need to patch anything in the surroundings of the code shown in Image
62.

If Olly has stopped at 0x40FB0D, press F9 to let the service execute completely. If all of the patches were successfully
made, the dump at 0x6944A8 should look like this:

Image 63

6944A8 -> 80 00 00 00
6944AC -> 0F 00 00 00

6944B8 -> 0A 00 00 00

This is actually happening because UOE has expired on the computer where the essay is taking place, and despite the
fact that a necessary patch for this value was previously done, it is necessary to patch these new instructions to
prevent them from overwriting the value that the patch at 0x40BF54 is writing at 0x6944AC. In a few words, if the
service detects it has expired, it writes 0x00 twice, so we write 0x0F twice as well.

To save the patches applied to the sensitive parts all together, go to the dump and select from the lowest to the
highest memory address modified:

Image 64

Image 65

Lowest memory address modified: 0x40BE9B

Highest memory address modified: 0x40FBFE

Make these changes permanent by saving them into a new file, for instance: usboesrvPatched3.exe
Image 66

The reversing is just about to come to an end, but first the infinite loop set at the SSR Point must be removed. In
order to do so, follow these few and easy steps:

1) Open usboesrvPatched3.exe with Olly.

2) Go to 0x44AD70.

3) Set the original instruction: SUB ESP, 1C

4) Save the modification in a new file, usboesrvPatched4.exe

Finally, close any Olly instance still opened and rename files as shown below:

usboesrv.exe -> usboesrvPatched2.exe

usboesrvPatched4.exe -> usboesrv.exe

Now restart the service and if all of the patches have been made successfully, readers should be able to connect
remotely to more than two devices as the video below shows:
Video showing a fully-functional cracked version

In spite of not being protected with strong packers, UOE has been a very difficult victim to reverse. This is a clear
example of how cleaver-designed protection systems could be more effective than any packer which is not used
properly.

In my opinion, the best security is achieved when combining both a good protection scheme designed for developers
and the proper use of an efficient packer/protector. I consider that with little effort, the security of this service can be
strongly reinforced to make it a nightmare, even for experienced crackers.

I hope the developers of UOE read this tutorial and release a new version improving this excellent scheme they
designed. I will be waiting for that as a new challenge. Meanwhile, I will have a look to other software from the same
company.

FINAL NOTE: All of the patches shown at different stages across this tutorial are distributed as a part of the essay into
the file UOEPatchedService.7z .

MISSION ACCOMPLISHED !!! I hope you have enjoyed this tutorial.

Thanks
To my son Erik Damien for bringing happiness to my life...

From the depths of the abyss ...


[email protected]

You might also like