Getting Started
August 8th, 2025
Overview
The initial start for this section will discuss necessary Assembly functions. The actual reversing of malware will be conducted in the next section. I would also like to clarify that I am by no means an expert, and that this is a learning experience to me as much as it is for you!
Assembly Functions
General Purpose Registers
This can be thought of as the foundation for tasks and operations. They are held in the CPU's super-fast storage locations. When you want to compute an arithmetic operation, do a simple for loop, or grow gray hairs, the GPRs are in play.

Segments
As such, with every programming language, there must be a way to perform actions. The GP instructions perform basic movement, arithmetic, logic, program flow, and string operations that are used to write application and system software. Although we won't mention every data instruction, we will cover the important ones for Assembly programming.
Moving data between the memory and other regions of the CPU can be thought of as this:
When looking at a process, there is one task that must happen: segmentation. Think of your process as a pie; what segmentation does is cut that pie into varying sizes depending on a person's desired slice.
This is the same case for Segmentation, the segment registers are constantly used for numerous important tasks, from moving memory and data to fetching instructions. Each segment that they point to can be a different size, similar to how your friends may have different sizes for their pie.

Registers
Assembly uses Registers which are small and fast storage components within a CPU, they can be used for performing multiple tasks while maintaining efficiency. The types of registers include; General-Purpose Registers, Flag Registers, Segment Registers, Pointer Registers and Index Registers.
Registers can be paired with other instructions such as mov, add, or . The leading "E" indicates that it is a 32-bit register, meanwhile, a leading "R" would indicate a 64-bit register
General-Purpose Registers
General-Purpose Registers can be used to storage data, addresses or calculate.
EAX
Accumulator Register used for arithmetic purpose
EBX
Base Register used for addressing
ECX
Count Register used for loop operations
EDX
Data Register used in conjunction with EAX for certain operations
Registers also consist of their lower and higher bit counter parts. 32-bit registers use the "E" letter for extended registers, while 64-bit registers use the "R" letter for a full Register. These both stem from the 16-bit register which does not have a leading letter, consisting of AX
, BX
, CX
, and DX
. Lastly, there are 8-bit registers which are taken from the lower and higher half of a 16-bit register.
RAX
AH, AL
RBX
BH, BL
RCX
CH, CL
RDX
DH, DL

Index Registers
Index Registers consist of their 32 and 16-bit counterparts, which aid in addition and subtraction (sometimes), but are mainly used for indexed addressing.
RSI (64-bit) ESI (32-bit) SI (16-bit)
source index for string operations
RDI (64-bit) EDI (32-bit) Di (16-bit)
destination index for string operations
In terms of string operations, these are not to be confused with generic strings (such as print statements). These registers input and output from a buffer index and are generally used with the following functions:
MOVSB
- Move a byte fromESI
toEDI
MOVSW
- Move a word (16-bit)MOVSD
- Move a double word (32-bit)MOVSQ
- Move a quad word (64-bit)STOS
- Store fromAL/AX/EAX/RAX
toEDI/RDI
LDOS
- Load fromEDI/RDI
toAL/AX/EAX/RAX
An example of this would be the code listed below, the char buffer[400] allows a maximum of 400 bytes, which is correctly matched with the reading process of (0, buffer, 400); anything past this would result in a buffer overflow. The buffer pointer would be the EDI, as it will be used to point to the destination; an ESI is nowhere to be found due to .
int buffer()
{
char buffer[400];
int input;
input = read(0, buffer, 400);
printf("\n[+] user supplied: %d bytes!",input);
printf("\n[+] buffer content --> %s!", buffer);
return 0;
}
Pointer Registers
Pointer Registers are designed to hold a memory address from another location, handle function calls, point to data in memory, and assist in memory operations. They are commonly used to control micro-controllers by accessing the . Similar to all other registers, they consist of 64, 32, and 16-bit versions, respectively.
Instruction Pointer
RIP(64) EIP(32) IP(16)
stores the of the next instruction to be executed
Stack Pointer
RSP(64) ESP(32) SP(16)
provides the offset value within the program stack
Base Pointer
RBP(64) EBP(32) BP(16)
helps in referencing the parameter variables passed to a
Data Movement
X86 Assembly has an immense amount of data transfer instructions; someone like you and me may just lose their heads trying to understand everything. However, fret not, for we will only be covering the necessary Assembly instructions in accordance with our Malware Analysis, learning more is always a good thing, but for our sake, keeping our sanity is the first of our problems!
mov - move data from GPRs, move data between memory and GP/Segment Registers, or move immediately to GPRs
push - push onto a stack
pop - pop (remove) off the stack
xchg - exchange
bswap - byte swap
dst - destination (where a value is stored or written)
src - source (data being read or manipulated)
Debugging Example
#include <windows.h>
#include <stdio.h>
int main() {
puts("---/*Creating Open Handle*/---");
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION processinfo;
LPCWSTR path = L"C:\\Windows\\system32\\notepad.exe";
printf("Creating Process! \n");
CreateProcess(path, NULL, NULL, NULL, FALSE, 0, NULL, NULL, &info, &processinfo);
DWORD PID = processinfo.dwProcessId;
printf("[i] Current Process ID: %ld", PID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
if (hProcess == NULL) {
printf("[-] Could not open process, error: %ld", GetLastError());
return EXIT_FAILURE;
}
printf("\n[0x%p] Got a handle to the process!\n", hProcess);
CloseHandle(hProcess);
CloseHandle(processinfo.hProcess);
CloseHandle(processinfo.hThread);
puts("[>] Press Enter Key to Exit");
(void)getchar();
return EXIT_SUCCESS;
}
The C program above opens a handle from a specific , which then prints out the handle to the process using the OpenProcess Function.

Looking at the information provided by x64DBG, we can see the OpenHandle program
References
Last updated