[{"content":" What is a CPU? # The Central Processing Unit serves as the computer\u0026rsquo;s primary processing engine. It executes software programs by following sequences of instructions that define computational tasks, mathematical calculations, and logical decisions. Think of it as the brain that interprets and carries out every operation your computer performs.\nRegister System # High-speed storage cells built directly into the CPU for immediate data access:\nGeneral Purpose Registers: Hold data currently being processed Address Registers: Store memory locations for data retrieval Status Registers: Track the state of operations and system flags Instruction Registers: Hold the current instruction being executed Registers operate at CPU speed, making them thousands of times faster than accessing main memory. ALU - Arithmetic Logic Unit # The computational workhorse of the processor that handles:\nMathematical Operations: Addition, subtraction, multiplication, division Logical Operations: Boolean logic (AND, OR, NOT, XOR) Comparison Operations: Determining relationships between values Bit Manipulation: Shifting and rotating binary data The ALU receives operands (data to work with) and produces results that feed back into the system for further processing or storage. Control unit # The management system that coordinates all CPU activities:\nInstruction Management: Fetches program instructions from memory Operation Sequencing: Ensures instructions execute in proper order Resource Coordination: Directs data flow between components Timing Control: Synchronizes operations with the system clock CPU Processing Cycle # Every instruction follows this fundamental sequence:\nPhase 1 - Instruction Fetch # Control unit retrieves the next instruction from memory Instruction address comes from the program counter Retrieved instruction loads into the instruction register Phase 2 - Instruction Decode # Control unit analyzes the instruction\u0026rsquo;s operation code (opcode) Determines what operation to perform Identifies required operands and their locations Phase 3 - Instruction Execute # ALU performs the specified operation Results are stored in appropriate registers or memory System flags are updated based on the operation outcome Program counter advances to the next instruction This cycle repeats millions or billions of times per second during program execution. graph TD CPU[\"`CPU : Central Processing Unit`\"] %% Main Components CU[\"`Control Unit : Manages operations`\"] ALU[\"`ALU : Does calculations`\"] REG[\"`Registers : Fast storage`\"] %% External MEM[\"`Memory : RAM`\"] %% Connections CPU --\u003e CU CPU --\u003e ALU CPU --\u003e REG CU -.-\u003e|Controls| ALU CU -.-\u003e|Manages| REG ALU -.-\u003e|Uses data from| REG CU \u003c-.-\u003e|Fetch instructions| MEM %% Styling classDef cpu fill:#e3f2fd,stroke:#1976d2,stroke-width:3px classDef component fill:#f1f8e9,stroke:#388e3c,stroke-width:2px classDef memory fill:#fff3e0,stroke:#f57c00,stroke-width:2px class CPU cpu class CU,ALU,REG component class MEM memory Memory hierarchy # The memory hierarchy represents the organized structure of different storage systems in a computer, arranged by speed, capacity, and cost. Faster memory is more expensive and smaller, while slower memory is cheaper and larger.\ngraph LR; reg[Registers] --\u003e cache[Cache] --\u003e ram[RAM] --\u003e storage[Storage] storage --\u003e ram --\u003e cache --\u003e reg graph LR A[\"`⚡ High Speed 📦 Low Capacity`\"] --\u003e B[\"`🐢 Low Speed 📦 High Capacity`\"] B --\u003e A %% Optional styling for clarity classDef speed fill:#4caf50,color:#fff,stroke:#333,stroke-width:2px; classDef capacity fill:#2196f3,color:#fff,stroke:#333,stroke-width:2px; class A speed; class B capacity; RAM # RAM (Random Access Memory) serves as the computer\u0026rsquo;s primary workspace - the main memory where active programs and data reside during execution.\nKey Characteristics:\nVolatile Memory: Contents disappear when power is lost Direct Access: CPU can reach any memory location instantly Working Space: Holds running programs, operating system, and active data Access Time: 50-100 nanoseconds Capacity: Typically 8GB-32GB in modern systems In reverse engineering, RAM contains running malware that can be captured through memory dumps for analysis. Cache # Cache acts as a high-speed buffer between the CPU and RAM, storing copies of frequently accessed data for instant retrieval.\nCache Levels:\nL1 Cache: Built into CPU core, 32-64 KB, 1-2 clock cycles L2 Cache: Close to CPU, 256KB-1MB, 3-10 clock cycles L3 Cache: Shared among cores, 4-32MB, 10-40 clock cycles How it works:\nCache Hit: Data found in cache - fast access Cache Miss: Data not in cache - must fetch from slower memory Temporal Locality: Recently used data likely to be accessed again Spatial Locality: Nearby memory locations often accessed together Storage # Storage provides permanent, non-volatile memory that persists data when the computer is powered off.\nTypes:\nHDD (Hard Disk Drive): Magnetic storage, 5-15ms access time, high capacity SSD (Solid State Drive): Flash memory, 0.1-0.2ms access time, faster but more expensive NVMe SSD: Direct PCIe connection, 3-7 GB/second transfer rates Malware often hides in storage through boot sector infections, hidden files, or encrypted payloads. Clock Frequency # The system clock generates electrical pulses that synchronize CPU operations:\nClock Speed: Measured in Hertz (cycles per second) Modern Speeds: Typically 2-5 GHz (billion cycles per second) Performance Impact: Higher frequencies allow more instructions per second Trade-offs: Faster clocks consume more power and generate more heat Input/Output systems and peripherals # The I/O subsystem manages communication between the computer and external devices, enabling user interaction and data exchange with the outside world.\nI/O Controllers # Specialized circuits that manage communication with peripheral devices:\nFunction: Translate between CPU signals and device-specific protocols Buffer Management: Store data temporarily during transfers Status Monitoring: Track device availability and error conditions Interrupt Handling: Notify CPU when operations complete Common Peripherals # Input Devices:\nKeyboard: Converts keystrokes into digital signals Mouse: Tracks movement and button clicks Microphone: Captures audio input for processing Camera: Digitizes visual information Output Devices:\nMonitor: Displays visual information from the graphics subsystem Speakers: Convert digital audio signals to sound waves Printer: Creates physical copies of digital documents Storage Interfaces:\nUSB: Universal Serial Bus for connecting various devices SATA: Serial ATA for connecting internal storage drives PCIe: High-speed expansion slots for graphics cards and NVMe drives Malware can exploit I/O systems through malicious USB devices, keyloggers, or network interface vulnerabilities. Number systems # Understanding different number systems is crucial for computer science and reverse engineering, as computers operate using binary while humans prefer decimal representation.\nbinary # The foundation of all digital computing, using only two digits: 0 and 1.\nKey Concepts:\nBase-2 System: Each position represents a power of 2 Bit: Single binary digit (0 or 1) Byte: 8 bits grouped together Word: CPU\u0026rsquo;s natural data size (32-bit or 64-bit) Position Values:\n128 64 32 16 8 4 2 1 2⁷ 2⁶ 2⁵ 2⁴ 2³ 2² 2¹ 2⁰ Example Conversion:\nBinary: 10110101 Decimal: 128 + 32 + 16 + 4 + 1 = 181 Binary Operations:\nAND: 1 \u0026amp; 1 = 1, all others = 0 OR: 0 | 0 = 0, all others = 1 XOR: Same bits = 0, different = 1 NOT: Flips all bits (0→1, 1→0) hexadecimal # Base-16 system using digits 0-9 and letters A-F, providing a compact way to represent binary data.\nHexadecimal Digits:\n0 1 2 3 4 5 6 7 8 9 A B C D E F 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Conversion Relationships:\n4 binary bits = 1 hex digit 2 hex digits = 1 byte 8 hex digits = 32-bit value Examples:\nBinary: 1010 1100 1111 0001 Hex: A C F 1 Result: 0xACF1 Decimal 255 = Binary 11111111 = Hex 0xFF Common Hex Values:\n0xFF: Maximum byte value (255) 0x00: Minimum value (0) 0xDEADBEEF: Common debug value 0x90: NOP instruction in x86 assembly Memory addresses, opcodes, and data values in reverse engineering are typically displayed in hexadecimal for readability. decimal # The familiar base-10 system humans use daily, with digits 0-9.\nPosition Values:\n1000 100 10 1 10³ 10² 10¹ 10⁰ Conversion Methods:\nBinary to Decimal: Sum powers of 2 for each 1-bit Hex to Decimal: Sum powers of 16 for each position Decimal to Binary: Repeatedly divide by 2, collect remainders Decimal to Hex: Repeatedly divide by 16, collect remainders Basic networking concepts # Network communication enables computers to exchange data across local and global connections, forming the backbone of modern computing infrastructure.\nTCP/IP # The Transmission Control Protocol/Internet Protocol suite provides the fundamental framework for internet communication.\nIP (Internet Protocol):\nFunction: Routes data packets between network nodes IPv4: 32-bit addresses (192.168.1.1) IPv6: 128-bit addresses for expanded address space Packet Structure: Headers contain source, destination, and routing information TCP (Transmission Control Protocol):\nReliable Delivery: Guarantees packet arrival and correct order Connection-Oriented: Establishes sessions before data transfer Error Correction: Retransmits lost or corrupted packets Flow Control: Manages transmission speed based on receiver capacity Three-Way Handshake:\nSYN: Client requests connection SYN-ACK: Server acknowledges and responds ACK: Client confirms, connection established graph TD A[Client] --\u003e|SYN| B[Server] A --\u003e|ACK| B B --\u003e|SYN-ACK| A B --\u003e C[Connection Established] ports # Logical endpoints that allow multiple network services to operate simultaneously on a single computer.\nPort Ranges:\nWell-Known Ports (0-1023): Reserved for system services Registered Ports (1024-49151): Assigned to specific applications Dynamic Ports (49152-65535): Temporary assignments for client connections Common Port Numbers:\nPort 80: HTTP web traffic Port 443: HTTPS secure web traffic Port 22: SSH secure shell Port 21: FTP file transfer Port 25: SMTP email sending Port 53: DNS domain name resolution Port 3389: RDP remote desktop Malware often uses uncommon ports or masquerades as legitimate services to evade detection during network analysis. protocols # Standardized rules that govern how data is formatted, transmitted, and received across networks.\nApplication Layer Protocols:\nHTTP/HTTPS: Web browsing and API communication FTP/SFTP: File transfer services SMTP/POP3/IMAP: Email communication DNS: Domain name to IP address translation DHCP: Automatic IP address assignment Transport Layer:\nTCP: Reliable, connection-oriented communication UDP: Fast, connectionless communication (no delivery guarantee) Network Layer:\nIP: Routing between different networks ICMP: Error reporting and network diagnostics (ping, traceroute) Common Protocol Analysis:\nWireshark: Packet capture and analysis tool Netstat: Display active network connections Nmap: Network discovery and port scanning tcpdump: Command-line packet analyzer Security Implications:\nPacket Sniffing: Intercepting network communications Man-in-the-Middle: Intercepting and modifying traffic Port Scanning: Discovering open services for potential exploitation Protocol Tunneling: Hiding malicious traffic within legitimate protocols Understanding network protocols is essential for analyzing malware communication, command and control channels, and data exfiltration techniques. ","date":"31 August 2025","externalUrl":null,"permalink":"/guides/reveng/arch/","section":"Guides","summary":"Learn the foundational elements that make up a modern computer system.","title":"0. Basic Components","type":"guides"},{"content":" The x86 architecture is one of the most widely used processor designs in the world.\nIt powers everything from classic PCs running MS-DOS to modern operating systems like Windows and Linux.\nJust be patient and try to gather as much information as possible before the learning-by-doing phase. Modes of Operation # The x86 processor family (Intel IA-32 and 32-bit AMD) can work in different \u0026ldquo;modes.\u0026rdquo;\nThese modes decide how programs run and what level of control they have over the system.\nProtected Mode (Modern Default) # The native mode of modern x86 CPUs. Each program gets its own memory space (segments). Prevents one program from interfering with others. Used in most modern operating systems (Windows, Linux, etc.). Virtual-8086 Mode (Sub-mode of Protected Mode) # Lets old programs (like MS-DOS software) run safely inside Protected Mode. Creates a sandbox environment for legacy code. Example: Windows XP could run multiple DOS programs at the same time. Real-Address Mode (Old-School Mode) # Works like the original Intel 8086 CPU. Programs have direct access to memory and hardware. No protection → one bad program can crash the whole system. Common in older systems like MS-DOS or Windows 98. System Management Mode (SMM) # A special hidden mode not used by normal programs. Handles low-level system tasks such as: Power management (sleep, battery) Security checks Runs invisibly in the background, controlled by the BIOS or hardware vendor Basic Execution Environment # Address Space # In 32-bit protected mode, a program can address a linear address space of up to 4 GB. Starting with the P6 processor, Extended Physical Addressing allows up to 64 GB of physical memory. In real-address mode, programs can only address 1 MB of memory. In virtual-8086 mode, each program has its own 1 MB address space, even if multiple programs are running. In 32-bit x86, registers and memory addresses are 32 bits wide. A 32-bit number can represent 2^32 = 4,294,967,296 unique values. That means the maximum addressable space = 4 GB (from 0x00000000 to 0xFFFFFFFF). Basic Program Execution Registers # Registers are high-speed storage locations inside the CPU.\nThey are much faster to access than memory, so loops and critical data often use registers instead of variables.\nThere are:\n8 general-purpose registers 6 segment registers 1 processor status flags register (EFLAGS) 1 instruction pointer (EIP) 32-bit General-Purpose Registers # EAX EBX ECX EDX EBP ESP ESI EDI\nEach of these 32-bit registers can also be accessed in smaller parts:\n32-Bit 16-Bit 8-Bit (High) 8-Bit (Low) EAX AX AH AL EBX BX BH BL ECX CX CH CL EDX DX DH DL The remaining general-purpose registers can only be accessed using 32-bit or 16-bit names, as shown in the following table:\n32-Bit 16-Bit ESI SI EDI DI EBP BP ESP SP Specialized Uses of General-Purpose Registers # EAX: used automatically for multiplication and division. Known as the accumulator register. ECX: used automatically as a loop counter. ESP: points to the stack (extended stack pointer). Rarely used for general arithmetic. ESI / EDI: used for fast memory transfers (source and destination index registers). EBP: used by high-level languages to reference function parameters and local variables (extended frame pointer). Segment Registers # In real-address mode, segment registers contain base addresses of memory areas (code, data, stack). In protected mode, they point to segment descriptor tables instead. Segment registers: CS, SS, DS, ES, FS, GS. Register Description CS (Code Segment) Points to the segment containing the executable program code. Instructions are fetched from the CS segment. DS (Data Segment) Points to the segment containing the data used by the program. Most memory references come from the DS segment. SS (Stack Segment) Points to the segment containing the stack, used for storing temporary data such as function parameters, return addresses, and local variables. ES (Extra Segment) Points to an additional data segment that can be used for various purposes, such as string operations. FS / GS Introduced with the Intel 80386 processor. Can be used for special purposes, such as thread-local storage or per-CPU data. Instruction Pointer # The EIP register contains the address of the next instruction to be executed. Certain instructions change EIP to branch to new code locations. EFLAGS Register # The EFLAGS register contains binary flags that either:\nControl how the CPU operates (control flags) Reflect the result of operations (status flags) Control Flags # Allow the CPU to break after each instruction. Enable interrupts. Switch into protected mode or virtual-8086 mode. Status Flags # These reflect outcomes of arithmetic and logic operations:\nCF (Carry flag): set if an unsigned result is too large. OF (Overflow flag): set if a signed result is too large or too small. SF (Sign flag): set if the result is negative. ZF (Zero flag): set if the result is zero. AF (Auxiliary Carry): set if a carry occurs from bit 3 to bit 4 in 8-bit operations. PF (Parity flag): set if the lowest byte has an even number of 1 bits. Intel64 for 64-bit Processing # Intel64 is Intel’s version of the x86-64 architecture, originally developed by AMD.\nIt allows processors to use a 64-bit linear address space, meaning programs can theoretically access a huge amount of memory. In practice, processors usually implement slightly less than the full 64 bits.\nThe physical memory supported can exceed 64 GB.\nIntel64 is backward compatible with 32-bit programs, so older software runs without performance loss.\nFirst used in the Pentium Extreme processor Also found in Intel Xeon, Celeron D, Pentium D, Core 2, Core i7, Atom, and newer Pentium 4 processors IA-32e Mode # Intel64 supports all the old IA-32 modes (Protected, Real-address, System Management) plus a new IA-32e mode for 64-bit processing.\nIA-32e mode has two sub-modes for 64-bit operating systems like Windows Vista or Linux:\nSub-mode Description Compatibility Mode Runs legacy 16-bit and 32-bit programs without recompilation. Operands are 16 or 32 bits, and the addressable memory range is 4 GB. 64-bit Mode Uses 64-bit addresses and operands, a greater number of registers, and extra instructions for handling large data. Memory segmentation is disabled, providing a flat 64-bit linear-address space. Applications in 64-bit mode cannot use real-address or segmented modes. Programs on a 64-bit OS can run in Compatibility mode (older software) or 64-bit mode (modern software).\nThis allows mixing old and new programs safely.\nIntel64 processors are used across many Intel families, but specifications vary. Common Assembly instructions # Before diving into assembly instructions, I recommend watching this video. It explains how the CPU works in detail, and even if you already know the basics, you’ll gain deeper insight into how opcodes, instructions, and flags work under the hood. mov — moves data from one location to another without modification.\nmov destination, source add — arithmetic addition; adds a value to the destination and stores the result.\nadd destination, value sub — arithmetic subtraction.\nsub destination, value inc — increments the destination by 1.\ninc destination dec — decrements the destination by 1.\ndec destination lea — load effective address; calculates an address and stores it in the destination (not the memory contents).\nlea destination, value cmp — compares two operands by subtracting the source from the destination.\ncmp destination, source The result is not stored anywhere, but the EFLAGS register is updated\n(Zero flag, Sign flag, Carry flag, Overflow flag, etc.) so that conditional jumps can act on it.\njmp — jumps to a new location, changing the instruction pointer.\njmp destination Other logic operations like or, and, and xor follow similar addressing rules as add and sub.\nAddressing # Instructions may require one or more operands.\nWhen an instruction uses two operands, the second is the source, which contains data or an address.\nAddressing uses segment registers and comes in three types:\nRegister addressing — the operand is in a register\nImmediate addressing — the operand is a constant in the instruction\nRegister and memory addressing — the operand points to a memory location\nReturn Address — a parameter that tells a function where to resume execution after it finishes. Functions can be called from multiple locations, so the return address ensures correct program flow.\nThe Stack # Each active function call has a stack frame storing all local variables.\nAll active frames are stored on the Stack, a critical memory structure.\nThe stack holds temporary data, function parameters, return addresses, and more.\nStack memory is static (allocated at compile-time), unlike the heap, which is dynamic (malloc() / new).\nLIFO behavior: Last In, First Out\nStack grows downwards: from high memory addresses to low addresses.\nStack Instructions # push value — decrements ESP by the size of value and copies it to the top of the stack.\npush value pop destination — copies the value from the top of the stack to the destination and increments ESP.\npop destination Extended Stack Instructions # These are often used by malware or low-level programs:\npusha — pushes all 16-bit registers (AX, CX, DX, BX, SP, BP, SI, DI) onto the stack.\npushad — pushes all 32-bit registers (EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI) onto the stack.\npopa — pops all 16-bit registers (inverse of pusha).\npopad — pops all 32-bit registers (inverse of pushad).\nThe Heap # The Heap is a memory region used for dynamic memory allocation. Unlike the stack (which is managed automatically), memory in the heap must be explicitly requested (malloc(), calloc(), new) and freed (free(), delete). Heap memory persists until freed — it does not vanish after a function returns. It’s generally larger than the stack but also slower because it requires system calls and bookkeeping. Heap memory is prone to fragmentation and vulnerabilities (e.g., heap overflows, use-after-free, double free). Managed in low-level C libraries by functions like brk() and mmap() in Linux. Key Points # Flexible size: Allocate as much as needed (until OS limits). Manual management: Programmer must release memory, or else leaks occur. Unordered growth: Unlike the stack’s LIFO model, the heap does not enforce a strict order. Heap grows upwards: From low memory addresses to higher ones (opposite to stack). code snippet # int *arr = malloc(10 * sizeof(int)); // allocate space for 10 ints free(arr); // release memory Conditional Jumps # Conditional jumps change the flow of execution based on the result of the previous comparison (cmp) or arithmetic instruction.\nThey rely on EFLAGS (Zero flag, Sign flag, Carry flag, Overflow flag, etc.).\nInstructions # je — Jump if Equal (a.k.a. jz, Jump if Zero).\ncmp eax, ebx je equal_label ; jump if eax == ebx jne — Jump if Not Equal\ncmp eax, ebx jne equal_label ; jump if eax == ebx ja — Jump if Above (a.k.a. jnbe, Jump if Not Below or Equal)\njae — Jump if Above or Equal (a.k.a. jnb, Jump if Not Below)\njb — Jump if Below (a.k.a. jnae, Jump if Not Above or Equal)\njbe — Jump if Below or Equal (a.k.a. jna, Jump if Not Above)\njg — Jump if Greater (a.k.a. jnle, Jump if Not Less or Equal)\njge — Jump if Greater or Equal (a.k.a. jnl, Jump if Not Less)\njl — Jump if Less (a.k.a. jnge, Jump if Not Greater or Equal)\njle — Jump if Less or Equal (a.k.a. jng, Jump if Not Greater)\njs — Jump if Sign (negative)\njns — Jump if Not Sign (non-negative)\njo — Jump if Overflow\njno — Jump if Not Overflow\njc — Jump if Carry\njnc — Jump if Not Carry\njp — Jump if Parity (a.k.a. jpe, Jump if Parity Even)\njnp — Jump if Not Parity (a.k.a. jpo, Jump if Parity Odd)\nWORD # A WORD is just two bytes of data. A DWORD is four bytes of data. A QWORD is eight bytes of data.\nBasic Examples # Stack frame # In this example, we\u0026rsquo;ll compile a simple C program and inspect how the function interacts with the stack during execution. This will help us understand how local and global variables are stored and accessed in memory.\n#include \u0026lt;stdio.h\u0026gt; int M = 5; // Global variable int add_func(int var) { int L = 0; // Local variable L = M + var; return L; } int main() { printf(\u0026#34;The result is %d\\n\u0026#34;, add_func(1)); return 0; } To compile the program in 32-bit mode :\ngcc -m32 stack_frame.c -o stack_frame # mode : 32-bit To verify the format :\nfile stack_frame stack_frame: ELF 32-bit LSB pie executable, Intel 80386 ... Function Prologue : push ebp mov ebp, esp sub esp, 0x10 #(1*16^1 + 0*16^0 = 16) Saves the previous base pointer.\nSets up a new stack frame for the function.\nAllocates space for local variables (16 bytes in this case). Accessing the Global Variable M : call __x86.get_pc_thunk.ax add eax,0x2e30 mov edx, [eax+0x30] Global variables are stored in the data segment, not the stack. These instructions calculate the address of M and load its value. Accessing the Function Parameter var : mov eax, [ebp+0x8] Parameters are passed on the stack. [ebp+0x8] points to the first argument var. Performing the Addition : add eax, edx mov [ebp-0x4], eax Adds M and var. Stores the result in the local variable L. Function Epilogue : mov eax, [ebp-0x4] leave ret Moves L into eax to return it. Restores the previous stack frame and returns to the caller. Bonus # 📄 CheatSheet : x86_64 ","date":"31 August 2025","externalUrl":null,"permalink":"/guides/reveng/x86asm/","section":"Guides","summary":"Learn the fundamentals of the 32-bit architecture and assembly language.","title":"1. x86 Crash Course","type":"guides"},{"content":"The x64 architecture (also known as AMD64 or Intel 64) is the 64-bit extension of the x86 instruction set.\nIt powers modern operating systems and applications, providing access to vastly more memory and additional registers compared to 32-bit x86.\nUnderstanding x64 builds directly on x86 knowledge. Focus on what\u0026rsquo;s different: more registers, new addressing modes, and calling conventions. Modes of Operation # The x64 processor introduces new operational modes while maintaining backward compatibility with x86.\nLong Mode (Native 64-bit Mode) # The native mode of x64 CPUs for 64-bit operating systems. Provides access to the full 64-bit address space and extended registers. Memory segmentation is largely disabled in favor of flat memory model. Used by modern 64-bit operating systems (Windows 10/11, Linux distributions, macOS). Compatibility Mode (Sub-mode of Long Mode) # Allows 32-bit and 16-bit programs to run on 64-bit operating systems. Programs execute as if running on a 32-bit processor. Transparent to the application - no recompilation needed. Example: Running old 32-bit games on Windows 11. Legacy Mode # When 64-bit extensions are disabled, processor behaves like traditional x86. Includes Protected Mode, Real-Address Mode, and Virtual-8086 Mode. Rarely used in modern systems except during boot process. Key Difference from x86: x64 eliminates Virtual-8086 mode in Long Mode and makes segmentation largely obsolete. Basic Execution Environment # Address Space # In 64-bit mode, applications can theoretically address 16 exabytes (2^64 bytes) of memory. In practice, current processors implement 48-bit virtual addressing, allowing 256 terabytes per process. Physical memory support varies by processor but can exceed 1 terabyte. Compatibility mode maintains the 4 GB limit for legacy applications. In 64-bit x64, addresses are 64 bits wide, but current implementations use only 48 bits. This means the usable address range goes from 0x0000000000000000 to 0x0000FFFFFFFFFFFF. The upper 16 bits must be copies of bit 47 (canonical addressing). Basic Program Execution Registers # x64 significantly expands the register set compared to x86, providing more storage for improved performance.\n64-bit General-Purpose Registers # RAX RBX RCX RDX RBP RSP RSI RDI R8 R9 R10 R11 R12 R13 R14 R15\nEach 64-bit register can be accessed in multiple sizes:\n64-Bit 32-Bit 16-Bit 8-Bit (Low) 8-Bit (High) RAX EAX AX AL AH RBX EBX BX BL BH RCX ECX CX CL CH RDX EDX DX DL DH Extended registers (R8-R15) have different naming conventions:\n64-Bit 32-Bit 16-Bit 8-Bit (Low) R8 R8D R8W R8B R9 R9D R9W R9B R10 R10D R10W R10B R11 R11D R11W R11B R12 R12D R12W R12B R13 R13D R13W R13B R14 R14D R14W R14B R15 R15D R15W R15B Pointer and index registers:\n64-Bit 32-Bit 16-Bit 8-Bit (Low) RSI ESI SI SIL RDI EDI DI DIL RBP EBP BP BPL RSP ESP SP SPL Specialized Uses of General-Purpose Registers # RAX: Return values and accumulator operations (64-bit version of EAX). RCX: Loop counter and 4th argument in Windows x64 calling convention. RDX: I/O operations and 3rd argument in Windows x64 calling convention. RSP: 64-bit stack pointer (critical for stack operations). RSI/RDI: String operations source/destination and function arguments. RBP: Frame pointer for accessing local variables and parameters. R8-R15: Additional general-purpose registers, often used for function arguments. Calling Conventions (Major Difference from x86) # Microsoft x64 Calling Convention (Windows) # First 4 arguments passed in registers: RCX, RDX, R8, R9 Additional arguments passed on stack (right to left) Shadow space: Caller allocates 32 bytes on stack for called function Return value in RAX Volatile registers: RAX, RCX, RDX, R8, R9, R10, R11 System V AMD64 Calling Convention (Linux/Unix) # First 6 arguments passed in registers: RDI, RSI, RDX, RCX, R8, R9 Additional arguments passed on stack (right to left) Return value in RAX Volatile registers: RAX, RCX, RDX, RSI, RDI, R8, R9, R10, R11 Critical Difference: x86 passes ALL arguments on the stack, while x64 uses registers for the first few arguments. This makes x64 function calls much faster but requires understanding different conventions per platform. Segment Registers # Segmentation is largely disabled in 64-bit mode. CS, SS are still present but function differently. FS and GS are used for special purposes like Thread Local Storage (TLS). DS, ES are ignored in 64-bit mode. Instruction Pointer # The RIP register contains the 64-bit address of the next instruction. Supports RIP-relative addressing - a new addressing mode unique to x64. Instructions can reference data relative to the current instruction pointer. RFLAGS Register # 64-bit version of the EFLAGS register. Contains the same status and control flags as x86. Additional bits reserved for future use. Status Flags (Same as x86) # CF (Carry flag): Set if unsigned arithmetic overflow occurs. OF (Overflow flag): Set if signed arithmetic overflow occurs. SF (Sign flag): Set if result is negative. ZF (Zero flag): Set if result is zero. AF (Auxiliary Carry): Set for BCD arithmetic operations. PF (Parity flag): Set if result has even parity. Common Assembly Instructions # The fundamental instructions remain the same but operate on 64-bit operands:\nmov — Move data between registers, memory, or immediate values.\nmov rax, rbx ; Move 64-bit value from rbx to rax mov eax, ebx ; Move 32-bit value (zeros upper 32 bits of rax) mov ax, bx ; Move 16-bit value mov al, bl ; Move 8-bit value add — Addition operation.\nadd rax, rbx ; 64-bit addition add rax, 1000 ; Add immediate value sub — Subtraction operation.\nsub rsp, 40 ; Subtract from stack pointer (common for stack allocation) inc / dec — Increment/decrement by 1.\ninc rcx ; Increment 64-bit register dec r8 ; Decrement extended register lea — Load Effective Address (very powerful in x64).\nlea rax, [rdi + rsi*2 + 8] ; Calculate address using complex addressing cmp — Compare operands (sets flags for conditional jumps).\ncmp rax, 0 ; Compare with zero cmp r8, r9 ; Compare two registers REX Prefix # x64 instructions may require a REX prefix byte to:\nAccess extended registers (R8-R15) Specify 64-bit operand size Access new 8-bit registers (SIL, DIL, BPL, SPL) mov r8, rax ; Requires REX prefix mov sil, al ; Requires REX prefix for SIL Addressing Modes # x64 supports all x86 addressing modes plus RIP-relative addressing:\nRegister Addressing # mov rax, rbx ; Source operand is in register rbx Immediate Addressing # mov rax, 0x12345678 ; 32-bit immediate (sign-extended to 64-bit) Memory Addressing # mov rax, [rbx] ; Direct memory reference mov rax, [rbx + 8] ; Base + displacement mov rax, [rbx + rcx*2] ; Base + index*scale mov rax, [rbx + rcx*2 + 8] ; Base + index*scale + displacement RIP-Relative Addressing (New in x64) # mov rax, [rip + 0x1234] ; Load from address relative to current instruction lea rbx, [rip + data_label] ; Load address of label relative to RIP RIP-relative addressing is crucial for Position Independent Code (PIC). It allows code to reference data without knowing absolute addresses, making ASLR (Address Space Layout Randomization) possible. The Stack (64-bit Behavior) # The stack operates the same way as x86 but with important differences:\nStack grows downward: From high addresses to low addresses LIFO behavior: Last In, First Out 64-bit addresses: All stack operations use 64-bit pointers 16-byte alignment: Stack must be aligned to 16-byte boundaries before function calls Stack Instructions # push — Push 64-bit value onto stack (decrements RSP by 8).\npush rax ; Push 64-bit register push qword [rbx] ; Push 64-bit memory value pop — Pop 64-bit value from stack (increments RSP by 8).\npop rax ; Pop into 64-bit register pop qword [rbx] ; Pop into 64-bit memory location Stack Frame Setup (64-bit) # ; Function prologue push rbp ; Save old frame pointer mov rbp, rsp ; Set new frame pointer sub rsp, 32 ; Allocate space for local variables ; Function epilogue mov rsp, rbp ; Restore stack pointer pop rbp ; Restore old frame pointer ret ; Return (pops return address into RIP) Stack Alignment: Before calling functions, RSP must be aligned to 16-byte boundary. The call instruction pushes 8 bytes, so you often need to adjust RSP by additional 8 bytes. The Heap (64-bit Considerations) # Larger address space: Can allocate much more memory than 32-bit systems Same principles: Dynamic allocation with malloc()/free() or new/delete 64-bit pointers: All heap addresses are 64-bit values Same vulnerabilities: Buffer overflows, use-after-free, double-free still apply // 64-bit heap allocation long long *big_array = malloc(1000000 * sizeof(long long)); // 8MB allocation free(big_array); Conditional Jumps # Conditional jumps work identically to x86, but operate on 64-bit comparisons:\ncmp rax, rbx ; Compare 64-bit values je equal_label ; Jump if equal jne not_equal ; Jump if not equal jg greater ; Jump if rax \u0026gt; rbx (signed) ja above ; Jump if rax \u0026gt; rbx (unsigned) All x86 conditional jump instructions are available with same mnemonics.\nBasic Examples # Stack Frame (64-bit Version) # Let\u0026rsquo;s examine the same C program compiled for 64-bit:\n#include \u0026lt;stdio.h\u0026gt; int M = 5; // Global variable int add_func(int var) { int L = 0; // Local variable L = M + var; return L; } int main() { printf(\u0026#34;The result is %d\\n\u0026#34;, add_func(1)); return 0; } Compile in 64-bit mode:\ngcc -m64 stack_frame.c -o stack_frame_x64 Verify the format:\nfile stack_frame_x64 stack_frame_x64: ELF 64-bit LSB pie executable, x86-64... x64 Assembly Analysis:\nFunction Prologue:\npush rbp ; Save old frame pointer (64-bit) mov rbp, rsp ; Set new frame pointer sub rsp, 16 ; Allocate 16 bytes for locals (aligned) Accessing Global Variable M:\nmov eax, DWORD PTR M[rip] ; RIP-relative addressing for global Accessing Function Parameter:\nLinux (System V): Parameter in edi register (first argument) Windows: Parameter in ecx register (first argument) ; Linux version mov edx, edi ; Parameter \u0026#39;var\u0026#39; passed in EDI register Performing Addition:\nadd eax, edx ; Add M + var mov DWORD PTR [rbp-4], eax ; Store in local variable L Function Return:\nmov eax, DWORD PTR [rbp-4] ; Move L into return register leave ; Equivalent to: mov rsp, rbp; pop rbp ret ; Return to caller Key Differences from x86: # Registers are 64-bit: RBP, RSP instead of EBP, ESP Parameter passing: Uses registers instead of stack for first few arguments RIP-relative addressing: Global variables accessed relative to instruction pointer Stack alignment: 16-byte alignment requirements Return address: 8 bytes instead of 4 bytes Advanced x64 Features # Position Independent Code (PIC) # RIP-relative addressing enables PIC, crucial for modern security:\nlea rax, [rip + data_section] ; Address calculated at runtime mov rbx, [rip + global_var] ; Access global data relatively Address Space Layout Randomization (ASLR) # x64\u0026rsquo;s large address space makes ASLR more effective Code, stack, and heap can be randomized across vast address ranges Makes exploitation significantly harder No-Execute (NX) Bit # Hardware support for marking memory pages as non-executable Stack and heap are typically non-executable by default Prevents many code injection attacks Performance Improvements # More Registers # 16 general-purpose registers vs 8 in x86 Reduces memory access and improves performance Better register allocation by compilers Improved Calling Conventions # Register-based parameter passing is faster than stack-based Reduced memory traffic for function calls Larger Address Space # No more 4GB memory limitations Applications can use system memory more effectively Bonus # 📄 The Art of Picking Intel Registers ","date":"31 August 2025","externalUrl":null,"permalink":"/guides/reveng/x64asm/","section":"Guides","summary":"Learn the fundamentals of the 64-bit architecture and assembly language.","title":"2. x64 Crash Course","type":"guides"},{"content":"Pointers are often considered one of the trickiest aspects of C programming—but they\u0026rsquo;re also what give the language its remarkable power and flexibility.\nWhat\u0026rsquo;s a Pointer? # A pointer is a special type of reference that stores the memory address of another variable, array, or data structure—making certain operations more efficient and flexible.\nPointer: A construct that behaves like a variable but holds the address of another object in memory. Think of memory as a massive apartment building. Each apartment has a unique address (memory address), and each apartment can store data (variables). A pointer is like having the address written on a piece of paper—it tells you where to find the actual apartment, but it\u0026rsquo;s not the apartment itself.\nint x = 42; // x is a variable storing the value 42 int *ptr = \u0026amp;x; // ptr is a pointer storing the address of x In this example:\nx contains the value 42 ptr contains the memory address where x is stored \u0026amp;x means \u0026ldquo;give me the address of x\u0026rdquo; *ptr means \u0026ldquo;give me the value at the address stored in ptr\u0026rdquo; Memory Layout in C Programs # Understanding how C organizes memory is crucial for mastering pointers. A typical C program\u0026rsquo;s memory is divided into several sections:\nCode Segment (Text Segment) # Contains the compiled machine code of your program Read-only and executable Shared among multiple instances of the same program Located at low memory addresses Data Segment # Initialized global and static variables Divided into read-write and read-only sections Exists for the entire program lifetime int global_var = 100; // Stored in initialized data segment static int static_var = 50; // Also in initialized data segment BSS Segment (Block Started by Symbol) # Uninitialized global and static variables Automatically initialized to zero by the system More memory-efficient than initialized data int uninitialized_global; // Stored in BSS, automatically set to 0 static int uninitialized_static; // Also in BSS Heap # Dynamic memory allocation area (malloc, calloc, realloc) Grows upward (toward higher addresses) Manual memory management required Larger but slower than stack Stack # Local variables, function parameters, return addresses Grows downward (toward lower addresses) Automatic memory management (LIFO - Last In, First Out) Fast but limited in size void function() { int local_var = 10; // Stored on the stack int array[100]; // Also on the stack } // Memory automatically freed when function ends Stack vs Heap Growth: The stack and heap grow toward each other. If they meet, you get a stack overflow or run out of memory! Pointer Declaration and Initialization # Basic Pointer Declaration # int *ptr; // Declares a pointer to int char *str; // Declares a pointer to char float *fptr; // Declares a pointer to float Pointer Initialization # int x = 42; int *ptr = \u0026amp;x; // Initialize pointer with address of x // Or declare then assign int *ptr2; ptr2 = \u0026amp;x; // Assign address of x to ptr2 NULL Pointers # int *ptr = NULL; // Initialize to NULL (safe practice) if (ptr != NULL) { // Always check before dereferencing printf(\u0026#34;%d\\n\u0026#34;, *ptr); } Best Practice: Always initialize pointers to NULL or a valid address. Uninitialized pointers contain garbage values and can cause crashes or security vulnerabilities. Pointer Operations # Address-of Operator (\u0026amp;) # The \u0026amp; operator returns the memory address of a variable.\nint x = 100; printf(\u0026#34;Value of x: %d\\n\u0026#34;, x); // Prints: 100 printf(\u0026#34;Address of x: %p\\n\u0026#34;, \u0026amp;x); // Prints: 0x7fff5fbff6ac (example) Dereference Operator (*) # The * operator accesses the value at the memory address stored in the pointer.\nint x = 100; int *ptr = \u0026amp;x; printf(\u0026#34;Value of x: %d\\n\u0026#34;, x); // Prints: 100 printf(\u0026#34;Value via pointer: %d\\n\u0026#34;, *ptr); // Prints: 100 printf(\u0026#34;Address in pointer: %p\\n\u0026#34;, ptr); // Prints address of x *ptr = 200; // Change x\u0026#39;s value through the pointer printf(\u0026#34;New value of x: %d\\n\u0026#34;, x); // Prints: 200 Pointer Arithmetic # Pointers can be incremented, decremented, and compared:\nint arr[5] = {10, 20, 30, 40, 50}; int *ptr = arr; // Points to first element printf(\u0026#34;%d\\n\u0026#34;, *ptr); // Prints: 10 printf(\u0026#34;%d\\n\u0026#34;, *(ptr + 1)); // Prints: 20 printf(\u0026#34;%d\\n\u0026#34;, *(ptr + 2)); // Prints: 30 ptr++; // Move to next element printf(\u0026#34;%d\\n\u0026#34;, *ptr); // Prints: 20 Important: When you add 1 to a pointer, it doesn\u0026rsquo;t add 1 byte—it adds the size of the data type it points to. For int*, adding 1 moves the pointer by 4 bytes (on most systems). Arrays and Pointers # Arrays and pointers are closely related in C. In many contexts, an array name acts like a pointer to its first element.\nArray-Pointer Equivalence # int arr[5] = {1, 2, 3, 4, 5}; int *ptr = arr; // Same as: int *ptr = \u0026amp;arr[0]; // These are equivalent: printf(\u0026#34;%d\\n\u0026#34;, arr[0]); // Array notation printf(\u0026#34;%d\\n\u0026#34;, *arr); // Pointer notation printf(\u0026#34;%d\\n\u0026#34;, *ptr); // Direct pointer access printf(\u0026#34;%d\\n\u0026#34;, ptr[0]); // Pointer with array notation Traversing Arrays with Pointers # int arr[5] = {10, 20, 30, 40, 50}; int *ptr = arr; // Method 1: Pointer arithmetic for (int i = 0; i \u0026lt; 5; i++) { printf(\u0026#34;%d \u0026#34;, *(ptr + i)); } // Method 2: Incrementing pointer ptr = arr; // Reset pointer for (int i = 0; i \u0026lt; 5; i++) { printf(\u0026#34;%d \u0026#34;, *ptr); ptr++; } Multidimensional Arrays and Pointers # int matrix[3][4] = { {1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12} }; // Pointer to first row int (*row_ptr)[4] = matrix; // Access element [1][2] (value 7) printf(\u0026#34;%d\\n\u0026#34;, matrix[1][2]); // Direct access printf(\u0026#34;%d\\n\u0026#34;, *(*(matrix + 1) + 2)); // Pointer arithmetic printf(\u0026#34;%d\\n\u0026#34;, row_ptr[1][2]); // Through row pointer Dynamic Memory Allocation # Dynamic memory allocation allows programs to request memory during runtime, providing flexibility for data structures whose size isn\u0026rsquo;t known at compile time.\nmalloc() - Memory Allocation # #include \u0026lt;stdlib.h\u0026gt; // Allocate memory for 10 integers int *ptr = (int*)malloc(10 * sizeof(int)); if (ptr == NULL) { printf(\u0026#34;Memory allocation failed!\\n\u0026#34;); return -1; } // Use the allocated memory for (int i = 0; i \u0026lt; 10; i++) { ptr[i] = i * i; // Store squares: 0, 1, 4, 9, 16... } // Print the values for (int i = 0; i \u0026lt; 10; i++) { printf(\u0026#34;%d \u0026#34;, ptr[i]); } // Don\u0026#39;t forget to free the memory! free(ptr); ptr = NULL; // Prevent accidental reuse calloc() - Cleared Allocation # // Allocate and initialize to zero int *ptr = (int*)calloc(10, sizeof(int)); if (ptr != NULL) { // All elements are already 0 for (int i = 0; i \u0026lt; 10; i++) { printf(\u0026#34;%d \u0026#34;, ptr[i]); // Prints: 0 0 0 0 0 0 0 0 0 0 } free(ptr); } realloc() - Resize Allocation # int *ptr = (int*)malloc(5 * sizeof(int)); // Initialize with values 0, 1, 2, 3, 4 for (int i = 0; i \u0026lt; 5; i++) { ptr[i] = i; } // Resize to hold 10 integers ptr = (int*)realloc(ptr, 10 * sizeof(int)); if (ptr == NULL) { printf(\u0026#34;Reallocation failed!\\n\u0026#34;); return -1; } // Old values are preserved, add new values for (int i = 5; i \u0026lt; 10; i++) { ptr[i] = i; } free(ptr); Memory Allocation Best Practices # Golden Rules of Dynamic Memory:\nAlways check if allocation succeeded (ptr != NULL) Free every allocated block with free() Set pointer to NULL after freeing to prevent double-free errors Never use freed memory (use-after-free vulnerability) Don\u0026rsquo;t free the same memory twice (double-free vulnerability) Common Pointer Pitfalls and Debugging # 1. Uninitialized Pointers # int *ptr; // Contains garbage value *ptr = 42; // CRASH! Writing to random memory // Fix: Initialize properly int *ptr = NULL; int x = 100; ptr = \u0026amp;x; *ptr = 42; // Safe 2. Dangling Pointers # int *create_local() { int local_var = 42; return \u0026amp;local_var; // DANGER! Returning address of local variable } int *ptr = create_local(); // ptr points to destroyed memory printf(\u0026#34;%d\\n\u0026#34;, *ptr); // Undefined behavior 3. Memory Leaks # void memory_leak() { int *ptr = (int*)malloc(100 * sizeof(int)); // Use ptr... // Forgot to call free(ptr)! return; // Memory is leaked } 4. Buffer Overruns # int arr[5] = {1, 2, 3, 4, 5}; int *ptr = arr; for (int i = 0; i \u0026lt; 10; i++) { // Should be i \u0026lt; 5 printf(\u0026#34;%d\\n\u0026#34;, ptr[i]); // Accessing beyond array bounds } 5. Double Free Errors # int *ptr = (int*)malloc(sizeof(int)); *ptr = 42; free(ptr); free(ptr); // CRASH! Double free error // Fix: Set to NULL after freeing free(ptr); ptr = NULL; Function Pointers # Function pointers allow you to store and call functions dynamically, enabling powerful programming patterns.\nBasic Function Pointers # #include \u0026lt;stdio.h\u0026gt; // Function declarations int add(int a, int b) { return a + b; } int multiply(int a, int b) { return a * b; } int main() { // Declare function pointer int (*operation)(int, int); // Point to add function operation = add; printf(\u0026#34;5 + 3 = %d\\n\u0026#34;, operation(5, 3)); // Prints: 8 // Point to multiply function operation = multiply; printf(\u0026#34;5 * 3 = %d\\n\u0026#34;, operation(5, 3)); // Prints: 15 return 0; } Array of Function Pointers # #include \u0026lt;stdio.h\u0026gt; int add(int a, int b) { return a + b; } int subtract(int a, int b) { return a - b; } int multiply(int a, int b) { return a * b; } int divide(int a, int b) { return b != 0 ? a / b : 0; } int main() { // Array of function pointers int (*operations[])(int, int) = {add, subtract, multiply, divide}; const char *op_names[] = {\u0026#34;+\u0026#34;, \u0026#34;-\u0026#34;, \u0026#34;*\u0026#34;, \u0026#34;/\u0026#34;}; int a = 12, b = 3; for (int i = 0; i \u0026lt; 4; i++) { printf(\u0026#34;%d %s %d = %d\\n\u0026#34;, a, op_names[i], b, operations[i](a, b)); } return 0; } Practical Examples and Applications # Example 1: Dynamic String Manipulation # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;string.h\u0026gt; char* create_greeting(const char* name) { const char* prefix = \u0026#34;Hello, \u0026#34;; const char* suffix = \u0026#34;! Welcome to C programming.\u0026#34;; // Calculate total length needed size_t total_len = strlen(prefix) + strlen(name) + strlen(suffix) + 1; // Allocate memory char* greeting = (char*)malloc(total_len); if (greeting == NULL) { return NULL; } // Build the greeting strcpy(greeting, prefix); strcat(greeting, name); strcat(greeting, suffix); return greeting; } int main() { char* msg = create_greeting(\u0026#34;Alice\u0026#34;); if (msg != NULL) { printf(\u0026#34;%s\\n\u0026#34;, msg); free(msg); // Don\u0026#39;t forget to free! } return 0; } Example 2: Linked List Implementation # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; // Node structure typedef struct Node { int data; struct Node* next; } Node; // Create a new node Node* create_node(int data) { Node* new_node = (Node*)malloc(sizeof(Node)); if (new_node != NULL) { new_node-\u0026gt;data = data; new_node-\u0026gt;next = NULL; } return new_node; } // Insert at beginning void insert_front(Node** head, int data) { Node* new_node = create_node(data); if (new_node != NULL) { new_node-\u0026gt;next = *head; *head = new_node; } } // Print the list void print_list(Node* head) { Node* current = head; while (current != NULL) { printf(\u0026#34;%d -\u0026gt; \u0026#34;, current-\u0026gt;data); current = current-\u0026gt;next; } printf(\u0026#34;NULL\\n\u0026#34;); } // Free the entire list void free_list(Node** head) { Node* current = *head; Node* next_node; while (current != NULL) { next_node = current-\u0026gt;next; free(current); current = next_node; } *head = NULL; } int main() { Node* head = NULL; // Build list: 3 -\u0026gt; 2 -\u0026gt; 1 -\u0026gt; NULL insert_front(\u0026amp;head, 1); insert_front(\u0026amp;head, 2); insert_front(\u0026amp;head, 3); print_list(head); // Clean up free_list(\u0026amp;head); return 0; } Example 3: Generic Swap Function # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; void generic_swap(void* a, void* b, size_t size) { // Allocate temporary space unsigned char* temp = (unsigned char*)malloc(size); if (temp == NULL) return; // Perform the swap memcpy(temp, a, size); // temp = a memcpy(a, b, size); // a = b memcpy(b, temp, size); // b = temp free(temp); } int main() { // Swap integers int x = 10, y = 20; printf(\u0026#34;Before swap: x=%d, y=%d\\n\u0026#34;, x, y); generic_swap(\u0026amp;x, \u0026amp;y, sizeof(int)); printf(\u0026#34;After swap: x=%d, y=%d\\n\u0026#34;, x, y); // Swap doubles double pi = 3.14159, e = 2.71828; printf(\u0026#34;Before swap: pi=%.2f, e=%.2f\\n\u0026#34;, pi, e); generic_swap(\u0026amp;pi, \u0026amp;e, sizeof(double)); printf(\u0026#34;After swap: pi=%.2f, e=%.2f\\n\u0026#34;, pi, e); return 0; } Memory Debugging Tools # Valgrind (Linux/macOS) # Valgrind is an excellent tool for detecting memory errors:\n# Compile with debugging info gcc -g -o program program.c # Run with Valgrind valgrind --leak-check=full --track-origins=yes ./program AddressSanitizer (GCC/Clang) # Built-in sanitizer for detecting memory errors:\n# Compile with AddressSanitizer gcc -fsanitize=address -g -o program program.c # Run normally - crashes will show detailed info ./program Static Analysis # Tools like cppcheck can catch issues at compile time:\ncppcheck --enable=all program.c Advanced Pointer Concepts # Pointer to Pointer (Double Pointers) # int x = 42; int *ptr = \u0026amp;x; // ptr points to x int **ptr2 = \u0026amp;ptr; // ptr2 points to ptr printf(\u0026#34;Value of x: %d\\n\u0026#34;, x); // 42 printf(\u0026#34;Value via ptr: %d\\n\u0026#34;, *ptr); // 42 printf(\u0026#34;Value via ptr2: %d\\n\u0026#34;, **ptr2); // 42 // Modify x through double pointer **ptr2 = 100; printf(\u0026#34;New value of x: %d\\n\u0026#34;, x); // 100 Const Pointers and Pointer to Const # int x = 10, y = 20; // Pointer to constant - can\u0026#39;t modify value through pointer const int *ptr1 = \u0026amp;x; // *ptr1 = 30; // ERROR! Can\u0026#39;t modify value ptr1 = \u0026amp;y; // OK - can change what ptr1 points to // Constant pointer - can\u0026#39;t change what it points to int * const ptr2 = \u0026amp;x; *ptr2 = 30; // OK - can modify value // ptr2 = \u0026amp;y; // ERROR! Can\u0026#39;t change pointer // Constant pointer to constant - can\u0026#39;t modify either const int * const ptr3 = \u0026amp;x; // *ptr3 = 30; // ERROR! // ptr3 = \u0026amp;y; // ERROR! Pointer Arrays vs Array of Pointers # // Array of pointers (each element is a pointer) char *names[] = {\u0026#34;Alice\u0026#34;, \u0026#34;Bob\u0026#34;, \u0026#34;Charlie\u0026#34;}; printf(\u0026#34;%s\\n\u0026#34;, names[0]); // Prints: Alice // Pointer to array (single pointer to entire array) int arr[5] = {1, 2, 3, 4, 5}; int (*ptr_to_array)[5] = \u0026amp;arr; printf(\u0026#34;%d\\n\u0026#34;, (*ptr_to_array)[0]); // Prints: 1 Security Considerations # Buffer Overflow Prevention # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;string.h\u0026gt; // Unsafe function - vulnerable to buffer overflow void unsafe_copy(char* dest, const char* src) { strcpy(dest, src); // No bounds checking! } // Safe function with bounds checking void safe_copy(char* dest, const char* src, size_t dest_size) { if (dest_size \u0026gt; 0) { strncpy(dest, src, dest_size - 1); dest[dest_size - 1] = \u0026#39;\\0\u0026#39;; // Ensure null termination } } int main() { char buffer[10]; // This could overflow the buffer // unsafe_copy(buffer, \u0026#34;This string is way too long for the buffer\u0026#34;); // This is safe safe_copy(buffer, \u0026#34;This string is way too long for the buffer\u0026#34;, sizeof(buffer)); printf(\u0026#34;Safe result: %s\\n\u0026#34;, buffer); return 0; } Input Validation # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; int* safe_malloc(size_t count, size_t size) { // Check for integer overflow if (count != 0 \u0026amp;\u0026amp; size \u0026gt; SIZE_MAX / count) { return NULL; } size_t total_size = count * size; if (total_size == 0) { return NULL; } return (int*)malloc(total_size); } int main() { size_t count = 1000000; int* ptr = safe_malloc(count, sizeof(int)); if (ptr == NULL) { printf(\u0026#34;Allocation failed or invalid parameters\\n\u0026#34;); return 1; } // Use ptr... free(ptr); return 0; } Performance Considerations # Cache-Friendly Memory Access # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;time.h\u0026gt; #define SIZE 1000 // Cache-friendly: access memory sequentially void sequential_access(int matrix[SIZE][SIZE]) { for (int i = 0; i \u0026lt; SIZE; i++) { for (int j = 0; j \u0026lt; SIZE; j++) { matrix[i][j] = i * j; } } } // Cache-unfriendly: access memory in column-major order void random_access(int matrix[SIZE][SIZE]) { for (int j = 0; j \u0026lt; SIZE; j++) { for (int i = 0; i \u0026lt; SIZE; i++) { matrix[i][j] = i * j; } } } Memory Pool Allocation # #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; typedef struct { void* memory; size_t size; size_t used; } MemoryPool; MemoryPool* create_pool(size_t size) { MemoryPool* pool = malloc(sizeof(MemoryPool)); if (pool) { pool-\u0026gt;memory = malloc(size); pool-\u0026gt;size = pool-\u0026gt;memory ? size : 0; pool-\u0026gt;used = 0; } return pool; } void* pool_allocate(MemoryPool* pool, size_t size) { if (pool \u0026amp;\u0026amp; pool-\u0026gt;used + size \u0026lt;= pool-\u0026gt;size) { void* ptr = (char*)pool-\u0026gt;memory + pool-\u0026gt;used; pool-\u0026gt;used += size; return ptr; } return NULL; } void destroy_pool(MemoryPool* pool) { if (pool) { free(pool-\u0026gt;memory); free(pool); } } Remember: Mastering pointers takes practice! Start with simple examples and gradually work up to more complex scenarios. Always think about memory management and security implications in your code. 📄 CheatSheet : C Pointers Reference Bonus # (Optional) \u0026ndash; if you want to master the pointers\n","date":"1 September 2025","externalUrl":null,"permalink":"/guides/reveng/cpointer/","section":"Guides","summary":"Master pointer manipulation and memory layout in C, with practical insights.","title":"3. C Pointers \u0026 Memory Management","type":"guides"},{"content":" Binary File Formats # Executable file formats # Executable file formats are specialized file types that contain instructions a computer can directly run. These files are the final product of compiling and linking source code, and they’re loaded into memory by the operating system’s loader to launch applications or perform tasks.\nFormat OS/Platform Extension(s) About PE Windows .exe, .dll Portable Executable; includes headers and sections for code/data ELF Linux, Unix-like .elf, none Executable and Linkable Format; modular and flexible Mach-O macOS, iOS none Used in Apple systems; supports fat binaries for multiple architectures MZ DOS .exe Legacy format; often a stub for newer formats COM DOS, Windows .com Very simple, flat memory model BIN Unix, embedded systems .bin Raw binary; often firmware or low-level code Understanding file formats matters for reverse engineering Operating system dependency : Different OS \u0026ndash; different formats Static vs Dynamic analysis preparation In this part, I give you the freedom to choose what you need and look it up on Google. If you don’t understand something from the videos, keep searching and exploring—don’t give up! 😄❤️ Portable Executable - Windows # A dive into the PE format \u0026lt;\u0026lt; Link PE Tools and Analysis # PE viewers - PEview, CFF Explorer, PE-bear Command line tools - dumpbin, objdump Executable and Linkable Format - Linux # A dive into the ELF format \u0026lt;\u0026lt; Link ELF Tools and Analysis # readelf - comprehensive ELF analyzer objdump - disassembly and headers hexdump - raw binary viewing file command - quick format identification Mach-O - Apple # A dive into the Mach-O format \u0026lt;\u0026lt; Link Mach-O Tools and Analysis # otool - object file displaying tool nm - symbol table viewer lipo - universal binary manipulation class-dump - Objective-C class information ","date":"3 September 2025","externalUrl":null,"permalink":"/guides/reveng/filebin/","section":"Guides","summary":"Overview of PE, ELF, and Mach-O structures with emphasis on headers, metadata, and resource analysis.","title":"4. File Formats \u0026 Binary Structure","type":"guides"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/tags/firmware/","section":"Tags","summary":"","title":"Firmware","type":"tags"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/tags/hard/","section":"Tags","summary":"","title":"Hard","type":"tags"},{"content":" Initial Analysis # ls -alh fw-backup-4M.bin -rw-r--r-- 1 user user 4.0M Oct 21 2024 fw-backup-4M.bin file fw-backup-4M.bin fw-backup-4M.bin: data strings -n 15 fw-backup-4M.bin Firmware Analysis - Brief Summary # Platform Identified: The firmware is built using the ESP-IDF framework for the ESP32 microcontroller, confirmed by log strings referencing ESP-IDF 2nd stage bootloader and code paths (e.g., esp32/rtc_time.c) [attached_image:1] \u0026hellip;.. Functionality: Bootloader logs indicate secure initialization, hardware setup, entropy (random number) configuration, and support for multicore processing. Investigation Direction: The device uses ESP32 hardware, and analysis should focus on bootloader routines, hardware checks, entropy setup, and potential network initialization or modification hooks. CPU Architecture # trou/cpu_rec_rs Determine which CPU architecture is used in a binary file. Rust 124 8 Parsing The firmware # A toolkit for helping you reverse engineer ESP32 firmware.\ntenable/esp32_image_parser A toolkit for helping you reverse engineer ESP32 firmware. Python 221 63 Extracting the app into elf. ","date":"18 November 2025","externalUrl":null,"permalink":"/posts/htb/sherlocks/malwareanalysis/opsalwarkameez2411/","section":"Posts","summary":"","title":"OpSalwarKameez24-3: Snake-Pill","type":"posts"},{"content":"","date":"18 November 2025","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/tags/easy/","section":"Tags","summary":"","title":"Easy","type":"tags"},{"content":" Initial Analysis # . ├── lockpick1 │ ├── bescrypt3.2 //ransomware │ ├── bescrypt.zip │ ├── DANGER.txt │ └── forela-criticaldata │ ├── co2_London │ ├── complaints.csv.24bes //encrypted file │ ├── complaints.csv.24bes_note.txt │ ├── customer-feedback.json.24bes │ ├── customer-feedback.json.24bes_note.txt │ ├── forela_uk_applicants.sql.24bes │ ├── forela_uk_applicants.sql.24bes_note.txt │ ├── it_assets.xml.24bes │ ├── it_assets.xml.24bes_note.txt │ ├── sales_forecast.xlsx.24bes │ ├── sales_forecast.xlsx.24bes_note.txt │ ├── trading-firebase_bkup.json.24bes │ └── trading-firebase_bkup.json.24bes_note.txt └── lockpick1.zip bescrypt3.2 # file bescrypt3.2 bescrypt3.2: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=2b6eafade391d7be39a8aff0d2e3a60aa8b6a4c2, for GNU/Linux 3.2.0, not stripped r2 -AA bescrypt3.2 [0x00001160]\u0026gt; afl 0x00001030 1 6 sym.imp.free 0x00001040 1 6 sym.imp.remove 0x00001050 1 6 sym.imp.fread 0x00001060 1 6 sym.imp.fclose 0x00001070 1 6 sym.imp.opendir 0x00001080 1 6 sym.imp.strlen 0x00001090 1 6 sym.imp.printf 0x000010a0 1 6 sym.imp.rewind 0x000010b0 1 6 sym.imp.snprintf 0x000010c0 1 6 sym.imp.closedir 0x000010d0 1 6 sym.imp.strcmp 0x000010e0 1 6 sym.imp.ftell 0x000010f0 1 6 sym.imp.readdir 0x00001100 1 6 sym.imp.malloc 0x00001110 1 6 sym.imp.fseek 0x00001120 1 6 sym.imp.fopen 0x00001130 1 6 sym.imp.fwrite 0x00001140 1 6 sym.imp.strstr 0x00001150 1 6 sym.imp.__cxa_finalize 0x00001160 1 33 entry0 0x00001190 4 34 sym.deregister_tm_clones 0x000011c0 4 51 sym.register_tm_clones 0x00001200 5 54 entry.fini0 0x00001240 1 9 entry.init0 0x00001780 1 9 sym._fini 0x00001746 1 56 main 0x000014d4 20 626 sym.process_directory 0x00001249 11 651 sym.encrypt_file 0x00001000 3 23 sym._init Disassemble and analyze main: This function is essential for understanding the overall program flow and logic. Review process_directory and encrypt_file functions: These appear to be central to the program\u0026rsquo;s core functionality and warrant detailed inspection. main() # [0x00001160]\u0026gt; s main [0x00001746]\u0026gt; pdf ; ICOD XREF from entry0 @ 0x1174(r) ┌ 56: int main (int argc, char **argv, char **envp); │ afv: vars(2:sp[0x10..0x18]) │ 0x00001746 55 push rbp │ 0x00001747 4889e5 mov rbp, rsp │ 0x0000174a 4883ec10 sub rsp, 0x10 │ 0x0000174e 488d05280a.. lea rax, str.bhUlIshutrea98liOp ; 0x217d ; \u0026#34;bhUlIshutrea98liOp\u0026#34; │ 0x00001755 488945f8 mov qword [var_8h], rax │ 0x00001759 488d05300a.. lea rax, str._forela_criticaldata_ ; 0x2190 ; \u0026#34;/forela-criticaldata/\u0026#34; │ 0x00001760 488945f0 mov qword [var_10h], rax │ 0x00001764 488b55f8 mov rdx, qword [var_8h] │ 0x00001768 488b45f0 mov rax, qword [var_10h] │ 0x0000176c 4889d6 mov rsi, rdx ; int64_t arg2 │ 0x0000176f 4889c7 mov rdi, rax ; char *arg1 │ 0x00001772 e85dfdffff call sym.process_directory │ 0x00001777 b800000000 mov eax, 0 │ 0x0000177c c9 leave └ 0x0000177d c3 ret [0x00001746]\u0026gt; The main function sets up two string variables:\nbhUlIshutrea98liOp /forela-criticaldata/ It then calls process_directory with these two strings as arguments.\nprocess_directory() # Opens the given directory path using opendir. If it fails, prints an error message. Iterates over each directory entry with readdir. Skips the special entries \u0026quot;.\u0026quot; and \u0026quot;..\u0026quot;. Constructs the full path of each entry. Recurses into subdirectories (d_type == 4) by calling itself. For regular files (d_type == 8), checks extensions: .txt, .sql, .pdf, .docx, .xlsx, .csv, .json, .xml If the file matches one of these extensions, prints a message and calls encrypt_file to encrypt the file. encrypt_file() # Opens the target file in binary read mode; prints an error on failure. Reads the entire file contents into memory. Encrypts each byte by XORing it with a repeated key derived from the second parameter (param_2). Writes the encrypted content to a new file with the .24bes extension. Creates a ransom note file (\u0026lt;filename\u0026gt;.24bes_note.txt) with payment instructions referring to the \u0026ldquo;bes24 group\u0026rdquo; and providing an email contact. Attempts to delete the original unencrypted file, printing an error if unsuccessful. decrypt.py # import os import glob def xor_decrypt(data, key): \u0026#34;\u0026#34;\u0026#34;XOR decrypt data with repeating key\u0026#34;\u0026#34;\u0026#34; key_bytes = key.encode() decrypted = bytearray() for i, byte in enumerate(data): decrypted.append(byte ^ key_bytes[i % len(key_bytes)]) return bytes(decrypted) # XOR key from the ransomware binary key = \u0026#39;bhUlIshutrea98liOp\u0026#39; # Directory containing encrypted files directory = \u0026#39;forela-criticaldata\u0026#39; # Find all .24bes files encrypted_files = glob.glob(f\u0026#39;{directory}/*.24bes\u0026#39;) print(f\u0026#34;Found {len(encrypted_files)} encrypted files to decrypt\\n\u0026#34;) # Decrypt each file for encrypted_file in encrypted_files: try: # Read encrypted data with open(encrypted_file, \u0026#39;rb\u0026#39;) as f: encrypted_data = f.read() # Decrypt the data decrypted_data = xor_decrypt(encrypted_data, key) # Remove .24bes extension to get original filename original_filename = encrypted_file.replace(\u0026#39;.24bes\u0026#39;, \u0026#39;\u0026#39;) # Save decrypted file with open(original_filename, \u0026#39;wb\u0026#39;) as f: f.write(decrypted_data) print(f\u0026#34;✓ Decrypted: {os.path.basename(encrypted_file)} -\u0026gt; {os.path.basename(original_filename)}\u0026#34;) except Exception as e: print(f\u0026#34;✗ Error decrypting {encrypted_file}: {e}\u0026#34;) print(f\u0026#34;\\nDecryption complete! All files restored.\u0026#34;) ","date":"12 November 2025","externalUrl":null,"permalink":"/posts/htb/sherlocks/malwareanalysis/lockpick/","section":"Posts","summary":"","title":"Lockpick","type":"posts"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/tags/ransomware/","section":"Tags","summary":"","title":"Ransomware","type":"tags"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/tags/xor/","section":"Tags","summary":"","title":"XOR","type":"tags"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/tags/aes/","section":"Tags","summary":"","title":"AES","type":"tags"},{"content":" Initial Analysis # . ├── DANGER.txt ├── malware │ └── update //ransomware ├── malware.zip └── share ├── countdown.txt ├── expanding-horizons.pdf.24bes //encrypted file .24bes └── takeover.docx.24bes update # file malware/update malware/update: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), statically linked, no section header Static analysis suggested the use of the UPX packer, a common tool both for legitimate compression and malware obfuscation.\nupx -d malware/update file malware/update malware/update: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6ad54a84d534384669012fd611094afe33875556, for GNU/Linux 3.2.0, not stripped radareorg/radare2 UNIX-like reverse engineering framework and command-line toolset C 22625 3142 r2 -AA malware/update [0x00001280]\u0026gt; ii [Imports] nth vaddr bind type lib name ――――――――――――――――――――――――――――――――――――― 1 0x00001030 GLOBAL FUNC printf 2 0x00001040 GLOBAL FUNC EVP_EncryptUpdate 3 0x00001050 GLOBAL FUNC curl_global_init 4 0x00001060 GLOBAL FUNC curl_global_cleanup 5 0x00001070 GLOBAL FUNC strlen 6 0x00001080 GLOBAL FUNC OPENSSL_init_crypto 7 0x00001090 GLOBAL FUNC ERR_print_errors_fp 8 0x000010a0 GLOBAL FUNC abort 9 0x000010b0 GLOBAL FUNC EVP_EncryptInit_ex 10 0x000010c0 GLOBAL FUNC EVP_aes_256_cbc 11 0x000010d0 GLOBAL FUNC EVP_CIPHER_CTX_new 12 ---------- GLOBAL FUNC __libc_start_main 13 0x000010e0 GLOBAL FUNC sleep 14 0x000010f0 GLOBAL FUNC memcpy 15 0x00001100 GLOBAL FUNC stat 16 0x00001110 GLOBAL FUNC fclose 17 0x00001120 GLOBAL FUNC EVP_CIPHER_CTX_free 18 0x00001130 GLOBAL FUNC strrchr 19 0x00001140 GLOBAL FUNC curl_easy_setopt 20 0x00001150 GLOBAL FUNC fflush 21 0x00001160 GLOBAL FUNC fopen 22 0x00001170 GLOBAL FUNC curl_easy_cleanup 23 0x00001180 GLOBAL FUNC curl_easy_init 24 0x00001190 GLOBAL FUNC curl_easy_perform 25 0x000011a0 GLOBAL FUNC putchar 26 0x000011b0 GLOBAL FUNC strcmp 27 0x000011c0 GLOBAL FUNC fprintf 28 0x000011d0 GLOBAL FUNC curl_easy_strerror 29 0x000011e0 GLOBAL FUNC fread 30 0x000011f0 GLOBAL FUNC opendir 31 0x00001200 GLOBAL FUNC readdir 32 0x00001210 GLOBAL FUNC puts 33 0x00001220 GLOBAL FUNC EVP_EncryptFinal_ex 34 0x00001230 GLOBAL FUNC snprintf 35 0x00001240 GLOBAL FUNC closedir 36 ---------- WEAK NOTYPE _ITM_deregisterTMCloneTable 37 0x00001250 GLOBAL FUNC remove 38 ---------- WEAK NOTYPE __gmon_start__ 39 ---------- WEAK NOTYPE _ITM_registerTMCloneTable 40 0x00001260 GLOBAL FUNC fwrite 42 0x00001270 WEAK FUNC __cxa_finalize [0x00001280]\u0026gt; Cryptographic functions from OpenSSL such as EVP_EncryptInit_ex, EVP_EncryptUpdate, EVP_aes_256_cbc, and EVP_EncryptFinal_ex indicate usage of AES encryption algorithms, suggesting the ransomware likely leverages AES-256-CBC for encrypting victim files.\n[0x00001280]\u0026gt; iz [Strings] main() # Uses get_key_from_url to fetch keys required for encryption.\nget_key_from_url() # Calls curl_global_init and curl_easy_init to initialize CURL library and create an easy handle.\nUses xor_cipher with a key (K1) to decrypt or generate the URL or headers stored in local_98.\nxor_cipher() # This function performs a byte-wise XOR operation between two input strings to encode or decode data. XOR ciphers are symmetric; applying the same function twice with the same key restores the original data.\nTakes three parameters: param_1: the key used for XOR operation. param_2: a pointer to the buffer to encrypt/decrypt. param_3: the input data to be encrypted/decrypted. [0x00001787]\u0026gt; s sym.get_key_from_url [0x00001af3]\u0026gt; pdf Crafting The URL # HESB = b7894532snsmajuys6 K1 = 0a434c49470f1c1d010c5d0a1845461f1f451b handle_directory() # This recursive function traverses the victim\u0026rsquo;s directories to encrypt targeted files and place ransom notes:\nOpens the directory specified by param_1. Downloads the ransom countdown file (countdown.txt) from a remote URL into the current directory. Iterates through directory entries; for each entry: If it is a subdirectory (excluding . and ..), recursively calls itself. If it is a file with a targeted extension (checked by is_target_extension), calls encrypt_file to encrypt it using keys. encrypt_file() # This function manages full-file encryption using the AES-256-CBC cipher via OpenSSL\u0026rsquo;s EVP interface. It opens the target file for reading and creates a new file for the encrypted output. It initializes the encryption context and iteratively reads chunks from the input file, encrypts each chunk by calling the encrypt function, then writes the encrypted data to the output. After encrypting all chunks, it finalizes encryption to account for padding, cleans up resources, closes the files, and securely deletes the original plaintext file.\nencrypt() # This function serves as a wrapper around OpenSSL\u0026rsquo;s EVP encryption update API. It encrypts a single block of data within a streaming encryption context. The function accepts a pointer to the encryption context and the length or flag related to the data block. It calls EVP_EncryptUpdate to process the data, and if encryption fails, it invokes error handling routines. This modular design separates block encryption for reuse during file encryption.\nAES-256-CBC # halloweeks/AES-256-CBC AES-256-CBC: A header-only library for AES encryption and decryption. Securely protect your data with this easy-to-integrate, single-header implementation. No external dependencies required. Ideal for projects requiring robust symmetric encryption. C 11 2 Key size: 256 bits (32 bytes)\nInitialization Vector (IV) size: 128 bits (16 bytes)\n32 + 16 = 48 Hmm\u0026hellip;\nlockpick2.0 xxd -ps -l 32 malware/updater f3fc056da1185eae370d76d47c4cf9db9f4efd1c1585cde3a7bcc6cb5889f6db lockpick2.0 xxd -ps -s 32 malware/updater 01448c7909939e13ce359710b9f0dc2e decrypt_files # ","date":"12 November 2025","externalUrl":null,"permalink":"/posts/htb/sherlocks/malwareanalysis/lockpick2/","section":"Posts","summary":"","title":"Lockpick2.0","type":"posts"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/posts/htb/sherlocks/malwareanalysis/","section":"Posts","summary":"Malware analysis involves dissecting and understanding malicious software\u0026rsquo;s behavior, code, and impact. Through static, dynamic, and code analysis techniques.","title":"Malware Analysis","type":"posts"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/posts/htb/sherlocks/","section":"Posts","summary":"Sherlocks are investigative challenges simulating OSINT and digital footprint analysis.","title":"Sherlocks","type":"posts"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/posts/htb/","section":"Posts","summary":"HTB is an interactive cybersecurity platform offering hands-on labs, challenges, and real-world simulations.","title":"HackTheBox","type":"posts"},{"content":"","date":"12 November 2025","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"","date":"2 September 2025","externalUrl":null,"permalink":"/cheatsheets/tools/","section":"Cheatsheets","summary":"Documentation of useful tools in the area.","title":"Tools","type":"cheatsheets"},{"content":"Tool for searching a given binary image for embedded files and executable code. Specifically, it is designed for identifying files and code embedded inside of firmware images.\nInstallation # sudo apt install python3-binwalk Usage # binwalk [OPTIONS] [FILE] Examples # Extract data binwalk --extract --dd=\u0026#34;.\u0026#34; Tux.jpg Use the --include and --exclude arguments to include or exclude specific signatures by name: binwalk --exclude=jpeg,png,gif /tmp/firmware.bin The signature names are displayed under the Signature Name column of the signature list.\n","date":"2 September 2025","externalUrl":null,"permalink":"/cheatsheets/tools/binwalk/","section":"Cheatsheets","summary":"extract embedded files and executable","title":"Binwalk","type":"cheatsheets"},{"content":"This is the cheatsheets section containing various tools and utilities documentation.\n","date":"2 September 2025","externalUrl":null,"permalink":"/cheatsheets/","section":"Cheatsheets","summary":"","title":"Cheatsheets","type":"cheatsheets"},{"content":"\n\n\n\n\n  \n\n\n\n","date":"30 August 2025","externalUrl":null,"permalink":"/guides/","section":"Guides","summary":"","title":"Guides","type":"guides"},{"content":"Reverse engineering isn’t just about reading assembly instructions, loading your program and hunting for strings . It’s a detective story in which you trace data flows, identify encryption routines, and uncover logic flaws that reveal the program’s objective . Mastering this craft equips you to find vulnerabilities in real-world software and malware.\nIf you don’t understand something, just Google it. ","date":"30 August 2025","externalUrl":null,"permalink":"/guides/reveng/","section":"Guides","summary":"Learn the basics of reverse engineering, binary analysis, and assembly inspection.","title":"Reverse Engineering","type":"guides"},{"content":"","date":"30 August 2025","externalUrl":null,"permalink":"/","section":"","summary":"","title":"","type":"page"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]