WeSeong Log in
← Back to posts
CPU and Security

OLLEYDBG practice and further organization of CPU and memory

OLLEYDBG practice and further organization of CPU and memory

I. Overview

Continuing from the previous post, this section addresses the areas that were lacking in the discussion of CPU and memory. We will examine the PE (Portable Executable) structure using the PEView program. Additionally, we will use the Ollydbg program to examine and manipulate the flow of a compiled process.



II. CPU and Memory

Central Processing UnitFor a more detailed explanation, please refer to the previous post. CPUs can be categorized into dual-core, hexa-core, and so on. Each core has its own set of registers, which is characteristic of modern MultitaskingThe process has become easier. It's important to note that terms like "dual-core" and "hexa-core" refer to features of a processor, not the CPU itself. Therefore, a "multi-processor" system would have more than one CPU, while "cores" are components within a single CPU. In other words, Multi-processorEach CPU can have multiple cores, similar to a hexa-core processor, and there can be two or more of these CPUs.


Let's revisit the structure of memory once more.


This is how it works: the kernel communicates with the hardware, exchanging signals. ShellIt is responsible for executing user commands. Therefore, all operating systems use the shell to send commands to the kernel, which in turn controls various hardware components such as the computer's speakers, monitor, and network card. Previously, in Linux

[SK쉴더스 SeSAC, Dong-Seoul Branch 1] Virtual machines, Linux, Ubuntu

This is a summary of the information, but it's been organized for clarity. Access to hardware is restricted for security and safety reasons. This means that access is only possible through the kernel, and to access the kernel, you must use a shell. The shell acts as a kind of interface, allowing users like us, who don't know machine language, to issue commands to the kernel and hardware. The relationship between parents and children.However, if you have experience with web development, you might easily think of inheritance. There's a main shell, and this shell is used to create various program shells, which is Main processOkay. Child processThis involves creating and running a shell program. In Windows, the main shell is '

'explorer.exe'When we open a browser, or run programs like Word or PowerPoint, the main shell is used. The newly created shell becomes a child process, and within it, the main thread and child threads each execute the program's functions. Main threadIt oversees the entire process. Child threadEach component has its specific function.


※ When creating a Windows process management module program, there are useful Python modules to consider. It's recommended to try using the Python WMI module, as it can be quite helpful.


The discussion about the kernel has become lengthy, but let's return to the topic of memory, which can be broadly categorized as: 'Stack area - Heap area - Data area - Code area' You can think of it as a sequence. In reality, the order of the data and code areas doesn't really matter, so the arrangement in the picture is like this. The reason for this is that the data area... This refers to where global variables or static variables are stored.The structure is as follows, and the code area is, as expected, Code related to the execution of the process is stored.These two areas have a specific order in which they are used. The memory address with a higher value is located below, while the address with a lower value is located above.It is located below the heap area. Saving from a high address to a lower addressIt can be done. Conversely, the hip area is Storing from a low address to a high addressThis is how it works. The stack area is Storing local variables or parametersand the hip area can be easily accessed whenever needed. Dynamically allocated and instantiated.It is stored there.



Ⅲ. PE (Portable Executable)

As I briefly mentioned in a previous post, Windows executable files (processes) are structured using the PE (Portable Executable) format. StructureIt's important to understand that structures, unlike lists or JSON formats, represent data in a byte-oriented manner, showing the code and data of a process. The way this structure is presented depends on the format, whether it's a ZIP file, a PE file, or something like MFT or VBR, each with its own distinct characteristics. Header structureIt contains detailed information, such as how each header section is divided by bytes, what function or role each section performs, and what the actual data is. (It shares similarities with...)


Although this has already been briefly explained, using a program that displays the PE structure allows us to examine the different types and classifications of headers, and to identify the actual address values. While some header values are fixed, others are dynamic. Therefore, when analyzing, it is important to understand what each byte represents. We will now conduct a practical exercise to simply manipulate the flow of a process.


  1. "Zero Flag Manipulation"

In this sample program, the actual main code begins at address 401000. Therefore, set a breakpoint and use the F9 shortcut key (which executes until the breakpoint) to move to address 401000. The Zero Flag returns 1 if the values being compared are equal, and 0 if they are not.


Looking at the red section, you can see that the CMP (compare) instruction in assembly language is used to perform a JNZ (jump if not equal) operation. This means that when you actually run the program using the F7 and F8 shortcuts,


If the value is changed to 1, the comparison operation will recognize that the values are equal, and the code will continue to execute without skipping.


  1. Changes to the JNZ instruction

So, instead of changing the "Zero Flag," could we instead modify the "JNZ" instruction to use "JE" (Jump if Equal) or "JZ" (Jump if Zero)? Of course, this is possible.


This demonstrates a smooth and consistent flow within the process. There are two ways to modify the command, as shown in the image. The JE and JZ commands, represented in hexadecimal as 75, can be changed to 74, or the commands themselves can be directly modified to JE, JZ.


  1. Process logic address modification

By examining the images, you can see that "Sample_0" is followed by "00401079." The part before "Sample_0" is the program name, and the part after it is the address, which specifies the code to be executed when the JNZ (Jump if Not Zero) instruction is used. What would happen if this code address was changed to "401000," which is the first address?



As shown in the image, the sequence will repeat endlessly from 401000 to 401048.


※ The addresses 401000, 401048, and so on, are technically speaking, OffsetIt refers to a relative address that is derived from a specific address in memory. It's useful to know about this offset, as it will be used frequently.


  1. Modifying comparison data using HxD

This involves modifying the actual value of a comparison operation that was written by the developer, using the HxD program.


The red section represents the actual comparison values. As you can see, the current time is being retrieved using "GetLocalTime." From the PE structure, I know that the starting point of the Base Code is 1000. And in the image, I can see that the hexadecimal value 7D5, along with the command, is located at address 401040. The "400000" prefix indicates the starting point of the process's memory, and since the actual code is based on the Base Code, starting from 1000, if you look at address 1040 using HxD,


You can observe this. Now, simply replace the current year with the current year, and then find the remaining 0 and 20, and replace them with the current month and day.


Afterward, I ran OllyDbg again to observe the program's behavior.


This demonstrates how the values are changing and successfully passing the CMP comparison operation.



※ The process operates by referencing address values within memory, using variables, functions, or data. The stack area starts at a high address and follows a LIFO (Last In, First Out) structure, gradually moving towards lower addresses. Therefore, when looking at the starting address of the code... Subtitle As commands ESPWe are subtracting 114 from the address, and ESP (the stack pointer) is also subtracting 114 from its current value to create space. This might seem confusing, but... Because the function operates from top to bottom, and moves from higher addresses to lower addresses, it requires a certain amount of memory (114) to function.



Review

Starting a new application and understanding how to use it has been much more challenging than the network issues I faced last week... 🤑 I felt like I lacked the necessary experience in forensics and reverse engineering, making it seem like an insurmountable task for someone without a background in those fields. However, I managed to get through this week, and I plan to continue posting a few more articles to review and consolidate what I've learned.