My Beginnings with Assembly

I’ve been diving deep lately into reverse engineering and malware analysis, a field that I’ve only had a limited exposure to in my day-to-day activities.  

Part of the learning is focused on writing simple assembly code. I’ve typically focused on high-level languages such as Python and Golang, so the syntax of assembly code is a fun learning curve. 

My starting point was learning the different ELF (Executable and Linkable Format) sections within the assembly code: 

.data - Section for storing initialized variables. 

.text - Section of the main code. 

.rodata - Section for storing constant variables (or read-only variables) 

.init - Section that contains executable code that performs initialization tasks, runs before any other code in the binary. 

.fini - Runs after the main program completes, closing the program. 

.plt – Procedure Linkage Table (PLT), and this is the code section that contains executable code

.got.plt – data section of the PLT

.rel.* - Contains relocation entries for the .text section

.init_array – holds pointers to functions that are executed before the main function is called

.fini_array - holds pointers to functions that are executed after the main function is called

.got – Global Offset Table (GOT), used for dynamic symbol resolution during runtime

.dynsym – stores the dynamic symbol table, used for dynamic linking

.dynstr – stores strings associated with dynamic symbols in the .dynsym table

.dynamic – contains information about dynamic linking, such as library dependencies and symbol resolution

.symtab – holds the symbol table used for linking and debugging

.strtab – stores strings for the names of symbols and sections referenced in .symtab

.debug – contains debugging information, such as line numbers and variable names (optional in production binaries)

.note – stores metadata, such as build information or identification notes

.tls – Thread Local Storage (TLS), used for variables that are unique to each thread

Although there are more sections (much more), I focused on a handful to learn some basic structures for reversing. 

I wrote a silly program that picked a direction, left or right, based on a random value generated. The assembly code was designed for x86_64 architecture, and relied on the .data and .text sections mentioned above. 

In the code, I learned how to work with jmp (jump), je (jump if equal), and rdtsc (Read Time-Stamp Counter). rdtsc is an assembly instruction used to generate pseudo-random numbers based on the CPU state. 

 

section .data
    msg db "Left or Right?", 0xA, 0         ; Prompt message with newline
    msg2 db "You chose left!", 0xA, 0       ; "Left" message
    msg3 db "You chose right!", 0xA, 0      ; "Right" message

section .text
    global _start

_start:
    ; Print the message
    mov rax, 1                   ; syscall number for sys_write
    mov rdi, 1                   ; file descriptor (stdout)
    mov rsi, msg                 ; address of the message
    mov rdx, 15                  ; length of the message
    syscall                      ; invoke the syscall

    ; Generate a random value using RDTSC
    rdtsc                        ; read the timestamp counter into edx:eax
    xor edx, eax                 ; combine high and low bits
    and edx, 1                   ; mask to get either 0 or 1

    ; Compare the random value
    cmp edx, 0
    je left                      ; if 0, jump to left
    jmp right                    ; otherwise, jump to right

left:
    ; Print the left message
    mov rax, 1                   ; syscall number for sys_write
    mov rdi, 1                   ; file descriptor (stdout)
    mov rsi, msg2                ; address of the left message
    mov rdx, 15                  ; length of the left message
    syscall                      ; invoke the syscall
    jmp exit                     ; exit the process

right:
    ; Print the right message
    mov rax, 1                   ; syscall number for sys_write
    mov rdi, 1                   ; file descriptor (stdout)
    mov rsi, msg3                ; address of the right message
    mov rdx, 16                  ; length of the right message
    syscall                      ; invoke the syscall
    jmp exit                     ; exit the process

exit:
    ; Exit the process
    mov rax, 60                  ; syscall number for sys_exit
    xor rdi, rdi                 ; return code 0
    syscall                      ; invoke the syscall

Many times, I’m performing investigations on network or control plane level traffic, or even potentially system logs. Deep diving into assembly has enabled me to expand my knowledge on the inner workings of attacks, from the malware author and protection stances, and I feel like it rounds out my other skills when it comes to performing investigations. 

There will be more to come on this topic in the coming weeks! I’ll be looking to add more details here and at this GitHub repo: https://github.com/hackersifu/reverse_engineering_cheat_sheet

Previous
Previous

Playing with DeepSeek

Next
Next

Forced Mentorship