0% found this document useful (0 votes)
81 views64 pages

205 String References and Basic Patching

Uploaded by

Saw Gyi
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)
81 views64 pages

205 String References and Basic Patching

Uploaded by

Saw Gyi
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/ 64

Malware Analysis

Professional

String References & Basic


Patching
S e c t i o n 0 2 | M o d u l e 0 5
© Caendra Inc. 2020
All Rights Reserved
Table of Contents

MODULE 05 | STRING REFERENCES & BASIC PATCHING


5.1 Introduction

5.2 String References

5.3 A Few Words Before Starting

5.4 Let’s Start . . .

5.5 Conclusion

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.2


Getting Started

Tools:
• Olly Debugger v1.10
• HxD Hex Editor
• Windows Calculator

Target:
• RE_Lab_5.zip

www.ollydbg.de MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.3


5.1

Introduction

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.4


5.1 Introduction

The most important and necessary first step in reverse


engineering is to manage to locate the algorithm(s) that
we are looking for among all those thousands and
thousands of lines of assembly code that we see using a
debugger or a simple disassembler.

This can be achieved in various ways, depending on each


case. Some of them are more widely used in different
scenarios.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.5
5.1 Introduction

In this module we will be using the simplest methods for


doing so, and we will review the various advantages and
disadvantages of each.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.6


5.2

String References

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.7


5.2 String References

Using various references to specific strings of the


executable module under analysis, we can, in some cases,
locate the piece(s) of code that we need to analyze further.

By string reference, we mean an assembly instruction that


refers to a memory location where a string is stored.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.8


5.3

A Few Words
Before Starting

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.9


5.3 A Few Words Before Starting

During the first steps in the world of reversing we will be


dealing with behavioral observations regarding the
execution of an application and how it reacts (or not) to our
inputs.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.10


5.4

Let’s Start...

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.11


5.4.1 Run the Target Executable and Observe its
Functionality

Of course, in this case, the only thing that this program


does is to evaluate the input of the user and notify the user
with a message stating whether the code entered was right
or wrong.

In order to test this application, we will write something


random and then push the check button to see what
happens.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.12
5.4.1 Run the Target Executable and Observe its
Functionality

The message we get, “This code is invalid!!!” isn’t very


encouraging, but it really is helpful because we now have a
clue what to search for in the code of this application.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.13


5.4.1 Run the Target Executable and Observe its
Functionality

Why are we so interested in that? The answer is simple. In


this case, we have at least two possibilities regarding the
output of this application to the user. It will either accept
the code or not. We don’t know the right code or the output
in that case, but we certainly know the result of the wrong
input. This resultant output can lead us to the point where
the decision was made, and this is exactly what we’re
looking for.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.14


5.4.2 Load the Executable in the Olly Debugger

You should now be at the Entry Point (EP). The entry point
of an executable module is the address of the first
instruction to be executed inside the module itself.

Sometimes, we might refer to the EP of a specific function.


In that case we refer to the starting address of that function
where we commonly see the function prologue (Chapter 2,
2.4).
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.15
5.4.2 Load the Executable in the Olly Debugger

Different compilers generate different patterns of code in


the EP, even different compilers made for the same
programming language.

However, for now, it is enough to be familiar with the


concept of EP.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.16


5.4.2 Load the Executable in the Olly Debugger

Figure 5.1 Entry Point of RE Course Challenge #1

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.17


5.4.2 Load the Executable in the Olly Debugger

The EP of this application is located at address


0x004020D0, and in this case the first instruction is a short
unconditional jump instruction (JMP) which redirects the
EIP to the address 0x004020E2.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.18


5.4.2 Load the Executable in the Olly Debugger

NOTE: There is a specific type of function called a ‘naked’


function. Functions declared as such direct the compiler
not to generate a function prologue or epilogue, in order for
the programmer to write their own custom code at the
beginning and at the end of those functions.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.19


5.4.3 Search for String References

It is time to search for the clue we found before, which is


the message that let us know that the code we entered was
invalid.

In the CPU window, right click, and then → Search for → All
referenced text strings

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.20


5.4.3 Search for String References

In the figure on the next slide, we can clearly see the


message we saw when we entered the wrong code.

In this case we were able to find the reference we were


looking for very quickly because it is located near the top of
the list generated by Olly.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.21


5.4.3 Search for String References

Figure 5.2 String References – RE Course Challenge #1

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.22


5.4.3 Search for String References

In some cases, in order to save time instead of manually


searching, we can right click → Search for text.

Personally, when searching through this utility, I uncheck the


‘Case sensitive’ option and check ‘Entire scope’. We can then
search for more references to our required text by clicking
Ctrl + L.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.23


5.4.3 Search for String References

So, now we know that there is an instruction referencing that


string at address 0x402E9E, and if you double click on that
line you will be automatically transferred there.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.24


5.4.4 Reversing the Logic
The following screenshot shows what you should be looking at by
now.

Figure 5.3 Instruction referencing the string


MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.25
5.4.4 Reversing the Logic

In the screenshot on the previous slide, we can see the two


possible outputs of this application. At address 0x00402E76
we can see the conditional jump instruction JNZ (jump if not
zero) where the decision is taken regarding the output.

A few instructions above at address 0x00402E6C we see a


CALL instruction and just before the unconditional jump we
see a TEST EAX, EAX instruction.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.26


5.4.4 Reversing the Logic

So what happens in reality is that the application is calling a


function, which returns a result to the EAX register.

Then, the application checks the value of EAX to see if it is


zero or not and if it is not, the conditional jump that follows
will redirect the execution to the bad message, otherwise the
execution will continue on with the good message.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.27


5.4.4 Reversing the Logic

Obviously, inside that function, the user-input data is


evaluated against correct data, but we will not dive in to
these details now since a basic overview of the application
logic is sufficient.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.28


5.4.5 Basic Memory Patching

Now that we understand the very basic logic of this


application, let’s try to ‘hack’ it, so that no matter what code
we enter, the application will always choose the execution
path of our choice.

In this case, it would be enough to simply patch only one


instruction, which is the conditional jump at address
0x00402E76.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.29


5.4.5 Basic Memory Patching

Here‘s the full instruction:


• 0x00402E76 75 1F JNZ 00402E97

Let’s break this down into pieces in order to explain what it does,
clearly.
• 0x00402E76 → VA of the first byte (0x75) of the instruction
• 0x75 → opcode (operation code) of the short JNZ jump
instruction.
• 0x1F → number of bytes to ‘skip’ or ‘jump’ by redirecting the EIP.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.30
5.4.5 Basic Memory Patching

In a few words, a short jump instruction (JZ, JNZ, JG, JL, etc.)
is a two-byte long instruction comprised of the opcode and
the number of bytes to redirect the EIP forward or backward
(-128 to +127 bytes).

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.31


5.4.5 Basic Memory Patching

So, in this case, the instruction starts at address 0x00402E76


with the opcode (0x75) and occupies one more byte space
for the number of bytes to jump (0x1F).

This means that this byte is located at 0x00402E76 + 1 =


0x00402E77.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.32


5.4.5 Basic Memory Patching

We can generally patch a conditional jump in three different


ways.

The first way is to substitute the whole instruction by using


NOPs (No Operation bytes). The opcode for this is 0x90.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.33


5.4.5 Basic Memory Patching

So in this case we would have:


• 0x00402E76 9090 NOP NOP

Select the instruction, then right click → Binary → Edit and


substitute both bytes with 0x90.

Run the application using F9 and enter a random code to see


the results, and then right click → Undo selection to restore
it back.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.34
5.4.5 Basic Memory Patching

Another way, which also requires modification of fewer bytes,


is to invert the logic of the jump.

In other words, turn the JNZ jump into a JZ (jump if zero)


jump. This will invert the logic in the sense that in this new
case, the application would accept every code as valid except
for the correct one.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.35


5.4.5 Basic Memory Patching

So, in this case we would have:


• 00402E76 74 1F JE 00402E97

Select the instruction, right click → Assemble and change


the JNZ to JZ and apply the modifications. As you see, only
the opcode has been changed.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.36


5.4.5 Basic Memory Patching

Enter again a code of your choice and evaluate the results.

Now restore the original code to test the final method.

Finally, instead of inverting the logic of the jump instruction,


we can modify it so that even if it does redirect the EIP, the
redirection will have no effect.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.37


5.4.5 Basic Memory Patching

We can achieve that by modifying the number that indicates


how many bytes to jump (0x1F in this case) to zero.

So, in this case we would have:


• 00402E76 75 00 JNZ 00402E78

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.38


5.4.5 Basic Memory Patching

As you can see, no matter which code we enter, the execution


will just continue with the next instruction which is exactly
what we want for this example.

Evaluate again the results by entering any code.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.39


5.4.6 Executable Patching Through Olly

During the previous section we saw different ways to patch a


conditional jump. However, all these were memory
modifications which are effective only in that specific running
instance of this application.

Often, we need to make these changes permanent which


implies that we need to write these modifications in the file
itself.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.40


5.4.6 Executable Patching Through Olly

In order to make these changes permanent, choose your


preferred method from above and once you apply it, select
the modified bytes → right click → Copy to executable →
Selection.

You can also choose ‘All modifications’ instead, unless you


have other modifications that you don’t want written to the
file.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.41


5.4.7 VA Offset Manual Calculation

As we mentioned in Chapter 4 (4.1), in order to permanently


modify the bytes we want, we have to know their offset inside
the physical file.

Olly Debugger does this calculation automatically (VA →


Offset), so you will not have to worry about this in the future,
but this doesn’t mean that you shouldn’t know how to do it in
case you ever need to.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.42


5.4.7 VA Offset Manual Calculation

In order to manually patch the bytes we are interested in


through a hex editor, we need first to know their offsets - their
position from the beginning of the file.

As we saw in Chapter 4 (4.3), the alignment of the executable


as mapped in memory is different from the one in the
physical file on the disk.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.43


5.4.7 VA Offset Manual Calculation

However, inside the header of the executable we can find all


the necessary information we need to manually calculate the
offset of a specific byte from its VA in memory.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.44


5.4.7 VA Offset Manual Calculation

1. We need to know which section the byte we are interested


in is. If you press Alt+M in Olly you will see how the
executable is mapped in memory along with all loaded
modules.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.45


5.4.7 VA Offset Manual Calculation

For this example, I am going to pick the third option from


above, so I want patch the byte located at VA 0x00402E77.

Let’s take a look at the memory map of the target executable.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.46


5.4.7 VA Offset Manual Calculation

Figure 5.4 Memory Map of RE Course Challenge #1

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.47


5.4.7 VA Offset Manual Calculation

As we can see the first section (.text), which contains the


executable code of this application, starts from VA
0x00401000 and has a size of 0x0023A000.

So, we know that our byte is within that range, and it belongs
to the first section.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.48


5.4.7 VA Offset Manual Calculation

2. We also should notice the Image Base, which is


0x00400000 - the default Image Base for an executable file in
Windows. Of course, this can be modified, but we won’t.

We need some more information to calculate the offset of


that byte, which we will retrieve from the header of this file.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.49


5.4.7 VA Offset Manual Calculation

3. Choose the first line (0x00400000) and Right click →


Dump in CPU.

Then, in the data window, right click → Special → PE header.


This will decode the header structures into a human-readable
format.

Scroll down until you see the following:


MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.50
5.4.7 VA Offset Manual Calculation

Figure 5.5 .text Section details of RE Course Challenge #1

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.51


5.4.7 VA Offset Manual Calculation

In the figure on the previous slide, we see the


IMAGE_SECTION_HEADER structure (Chapter 4) of the
section we are interested in. As you can see, the first member
of this structure stores the section name.

Of course, there might be cases in which more than one


section has the same name, but this is not a problem. Apart
from the fact that their order is going to be the same as in the
memory map; we can always identify them by the value of
their RVAs.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.52
5.4.7 VA Offset Manual Calculation

Let’s explain the few first lines once more.


• VirtualSize: The size of the section in memory.
• VirtualAddress: The RVA of the section in memory, not the
VA.
• SizeofRawData: Size of the section in the file.
• PointerToRawData: Starting offset of the section in the
file.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.53


5.4.7 VA Offset Manual Calculation

4. Now, we have all the necessary information we need to find the


offset of the byte using the following formula:

Byte_Offset = Byte_VA - (Image_Base + Section_RVA) +


PointerToRawData

Which, in this case, would be:


• Byte_Offset = 0x00402E77 - (0x400000 + 0x1000) + 0x600 =
0x2477
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.54
5.4.8 Manual Byte Patching

We can now load our target into the hex editor and press Ctrl+G to
enter the hex value of the offset of the byte we just calculated from
the beginning of the file.

You only need to: modify the 0x1F byte with 0x00, save the new
executable with another name, and evaluate the changes. This is
shown on the next slide.

You should, at this point, try to apply the other two fixes manually
to gain some practice.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.55
5.4.8 Manual Byte Patching

Figure 5.6 Byte Patched in RE Course Challenge #1

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.56


5.5

Conclusion

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.57


5.5 Conclusion

During this module we covered a lot of information on the


simplest method of locating an algorithm we are interested
in.

However, as we know, the simplest method is not always


the appropriate one to use. Indeed, this method might be
fast, but we cannot always rely on it. For example, what
would happen if those strings were encrypted? Most likely,
this method would have become useless.
MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.58
5.5 Conclusion

On the other hand, this doesn’t mean that this isn’t a


method that we can still use in many cases.

In the next chapter, we will be discussing a more reliable


method used in order to reach the parts of the code that we
want to examine and we’ll also evaluate some information
which can be retrieved from the stack.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.59


VIDEO

Check out the video on


String References and Basic
Patching!

To ACCESS your video, go


to the course in your
members area and click the
resources drop-down in the
appropriate module line.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.60


LAB
Put what you’ve learned to
practice with the
RE_Lab_5.zip!

To ACCESS your lab, go to


the course in your members
area and click the resources
drop-down in the
appropriate module line,
your file will then download.

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.61


References

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.62


References
Here’s a list of all references linked or used in this course.
Olly Debugger v1.10
www.ollydbg.de

HxD Hex Editor


www.mh-nexus.de/en/hxd/

Windows Calculator

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.63


Videos & Labs
Here’s a list of all videos and labs in this module. To ACCESS, go to the
course in your members area and click the resources drop-down in the
appropriate module line.

String References and Basic Patching

RE_Lab_5.zip

MAPv1: Section 02, Module 05 - Caendra Inc. © 2020 | p.64

You might also like