https://www.youtube.com/watch?v=75gBFiFtAb8&t=173s # X86 Assembler ## Intro file.c -> compiler -> instruction instruction = Opcode + Operand Assemble is language -> translate machine instruction to human readable ! ![image](https://hackmd.io/_uploads/HymcF0y4el.png) **Assembly**: `add rax, 1` **Machine Code**: `48 83 C0 01` **Binary Code**: `01001000 10000011 11000000 00000001` ## Compilation Stages ![image](https://hackmd.io/_uploads/BJl2Y0JEle.png) Interpreted languages are executed by an interpreter at runtime or compiled to an intermediate bytecode, which is then interpreted or JIT-compiled. They utilize pre-built libraries (usually written in C/C++) to execute their instructions. The CPU uses different electrical charges to represent 1 and 0. **Note**: Java uses a Java Virtual Machine (JVM) to execute bytecode, which is compiled from Java source code. # Computer Architecture [Von Neumann Architecture](https://en.wikipedia.org/wiki/Von_Neumann_architecture) (Modern Computer) **General-Purpose Computers** ![image](https://hackmd.io/_uploads/rJDJ5Rk4gg.png) Assembly language mainly interacts with the CPU and memory. Therefore, understanding computer architecture is essential for working with assembly language. ### Memory (Primary Memory) A computer's memory stores the temporary data and instructions of the currently running program. ### Cache ![image](https://hackmd.io/_uploads/BJtZcAy4gl.png) Cache runs at the same clock speed as the CPU. There are typically three levels of cache memory: - Level 1 (L1): Fastest, each CPU core has one. - Level 2 (L2): Shared between all CPU cores. - Level 3 (L3): Shared across all cores, slower than L1 and L2. ### RAM **Size**: Gigabytes to Terabytes Retrieving one instruction from a register takes only one clock cycle. L1 Cache needs a few clock cycles. Retrieving data from RAM takes around 200 cycles. - 32-bit: 2**32 = 0xffffffff - 64-bit: 2**64 = 0xffffffffffffffff ![image](https://hackmd.io/_uploads/Sy0Q5RJEex.png) The heap can store and retrieve data in any order. The .data section holds variables, and the .bss section holds unassigned variables. The .text section contains assembly instructions. ## I/O Storage The processor can access I/O devices using a bus interface. The bus acts as a "highway" to transfer data and addresses using electrical charges for binary data. Each bus has a capacity of bits it can carry simultaneously, typically a multiple of 4 bits, ranging up to 128 bits. Bus interfaces are also used to access memory and other components outside the CPU. Primary storage is volatile, but secondary storage is non-volatile. SSDs use non-volatile circuitry and a design similar to RAM, making them faster than HDDs. ### Speed | Component | Speed | Size | |:------------|:-----------------------------------|:--------------------| | `Registers` | Fastest | Bytes | | `L1 Cache` | Fastest, other than Registers | Kilobytes | | `L2 Cache` | Very fast | Megabytes | | `L3 Cache` | Fast, but slower than the above | Megabytes | | `RAM` | Much slower than all of the above | Gigabytes-Terabytes | | `Storage` | Slowest | Terabytes and more | # CPU Architecture The Control Unit (CU) is in charge of moving and controlling data. The ALU (Arithmetic/Logic Unit) is in charge of performing arithmetic and logical calculations. The efficiency of a CPU in processing instructions depends on its Instruction Set Architecture (ISA), which defines how instructions are executed. **RISC Architecture (Simple ISA)** - More cycles - Each cycle is short and takes less power **CISC Architecture (Complex ISA)** - Fewer cycles However, CISC instructions are more complex and typically require more time to complete. ## Clock Speed & Clock Cycle ![image](https://hackmd.io/_uploads/BkBtqC14xe.png) **Frequency (Hertz)**: 3 GHz = 3 billion cycles per second Modern processors have a multi-core design, allowing them to execute multiple cycles simultaneously. ## Instruction Cycle ![image](https://hackmd.io/_uploads/SyNccAJVgg.png) Each instruction cycle takes multiple clock cycles to finish. ### Sequential Instruction **Example**: add rax, 1 1. Fetch the address from the RIP register. 2. Read the binary instruction `48 83 C0 01`, decode it, and add 1 to the rax register. 3. Get the current value from rax (by the CU) and add 1 to it (by the ALU). 4. Store the new value back to rax. ![image](https://hackmd.io/_uploads/ryqo5RkNlx.png) Nowadays, modern processors can process multiple instructions in parallel due to multi-threading and multi-core designs. ![image](https://hackmd.io/_uploads/S1PhcAkEgl.png) ## Processor Specific Each processor understands a different set of instructions (ISA). e.g., machine code: `4883C001` - Intel processor uses the x86-64 instruction set → `add rax, 1` - ARM processor uses ARM's instruction set → `biceq r8, r0, r8, asr #6` ![image](https://hackmd.io/_uploads/Hy6TqC1Nxl.png) A single instruction set architecture (ISA) may have different syntaxes for each processor. Under the same ISA, but with different syntax: - Intel syntax: `add rax, 1` - AT&T syntax: `addb $0x1, %rax` ## Instruction Set Architecture ![image](https://hackmd.io/_uploads/H1OkjCyVxl.png) **CISC (Complex Instruction Set Computer)** Typically used in servers or personal computers. e.g., Intel and AMD processors **RISC (Reduced Instruction Set Computer)** Typically used in smartphones and modern laptops. e.g., ARM and Apple processors ## CISC vs. RISC ![image](https://hackmd.io/_uploads/BypfsRyVge.png) | Area | CISC | RISC | |:--------------------------------|:------------------------------------------------------------|:----------------------------------------------------| | Complexity | Favors complex instructions | Favors simple instructions | | Length of instructions | Longer instructions - Variable length (multiples of 8 bits) | Shorter instructions - Fixed length (32-bit/64-bit) | | Total instructions per program | Fewer total instructions - Shorter code | More total instructions - Longer code | | Optimization | Relies on hardware optimization (in CPU) | Relies on software optimization (in assembly) | | Instruction Execution Time | Variable - Multiple clock cycles | Fixed - One clock cycle | | Instructions supported by CPU | Many instructions (~1500) | Fewer instructions (~200) | | Power Consumption | High | Very low | | Examples | Intel, AMD | ARM, Apple | RISC processors are faster than CISC processors. ## Register, Address, Data Type ![image](https://hackmd.io/_uploads/Hk98iCyVll.png) ### Sub-Registers ![image](https://hackmd.io/_uploads/r1Nwo0y4xe.png) | Description | 64-bit Register | 32-bit Register | 16-bit Register | 8-bit Register | |:-------------------------------|:----------------|:----------------|:----------------|:---------------| | **Data/Arguments Registers** | | | | | | Syscall Number/Return value | `rax` | `eax` | `ax` | `al` | | Callee Saved | `rbx` | `ebx` | `bx` | `bl` | | 1st arg - Destination operand | `rdi` | `edi` | `di` | `dil` | | 2nd arg - Source operand | `rsi` | `esi` | `si` | `sil` | | 3rd arg | `rdx` | `edx` | `dx` | `dl` | | 4th arg - Loop counter | `rcx` | `ecx` | `cx` | `cl` | | 5th arg | `r8` | `r8d` | `r8w` | `r8b` | | 6th arg | `r9` | `r9d` | `r9w` | `r9b` | | **Pointer Registers** | | | | | | Base Stack Pointer | `rbp` | `ebp` | `bp` | `bpl` | | Current/Top Stack Pointer | `rsp` | `esp` | `sp` | `spl` | | Instruction Pointer 'call only'| `rip` | `eip` | `ip` | `ipl` | #### Memory Address #### Types of Address Fetching ![image](https://hackmd.io/_uploads/BkYoH7-4xg.png) ![image](https://hackmd.io/_uploads/ryl2rXW4gg.png) ![image](https://hackmd.io/_uploads/SkAyIXZNex.png) (i.e., Addressing Modes) Immediate Addressing The data is a constant or literal specified in the instruction, requiring no additional memory access to retrieve the value. Register Addressing Mode The processor retrieves the operand directly from the named register Direct Addressing Mode the instruction contains the full memory address of the operand Indirect Addressing Mode the instruction provides a reference (e.g., a memory address or a register) that contains the actual address of the operand. ### Address Endianness Address endianness is the order in which bytes are stored or retrieved from memory. ![image](https://hackmd.io/_uploads/ByzZImW4ll.png) ![image](https://hackmd.io/_uploads/SJ6Q8Q-4eg.png) ![image](https://hackmd.io/_uploads/H1EELmZ4gg.png) The Little Endian Address 0x7766554433221100 is not equal to the Big Endian0x7766554433221100 In little-Endian format, to store the string "meow", we would push its bytes in reverse order: w, o, e, w ### Data Types Common data types ![image](https://hackmd.io/_uploads/SkpB8QW4ee.png) we can't use a variable defined as byte with rax, as rax has a size of 8 bytes al byte ax word eax dword rax qword ## Execute file elements - Heap - calloc - malloc ### Stack Stack grows download (High Address -> low) Example High Address -> 0x2000 Low Address --> 0x1000 initial Stack SP = 0x2000 Push(A) SP = 0x1ffc Push(B) SP = 0x1ff8 PoP() SP = 0x1ffc SP -> Top pointer SB -> Base Address pointer ![image](https://hackmd.io/_uploads/Sk8fn8dQkl.png) ESP -> Pointer to top elements EBP -> - Register - Instruction ![image](https://hackmd.io/_uploads/By1hLUuQyg.png) # Register E-> extended -> 32 bit General Register - eax,ebx,ecx,edx,esi,edi Stack Register - ebp,esp,eip ## EAX (Accumulator Register) 1. Using in calculator or data moving 2. Saving function return value. ![圖片](https://hackmd.io/_uploads/rJvuSHNY0.png) ## EBX (Base Register) 1.Saving base Address 2.File Descriptor ### File Description FD 0 -> stdin Keyboard 1 -> stdout Screen 2 -> stderr Screen ``` e.g mov ebx,0 ;write something in or mov ebx,1 ;Output somthing in screen ``` ``` section .data array db 10, 20, 30, 40, 50 // db -> defined Byte 意思, array -> base Address ``` ``` section .bss //未初始化的全局和靜態變量 result resb 1 // result -> ArraryName ``` `mov ebx, array` -> adding Array Address to ebx `add ebx, 2` -> bias = 2 (EBX->array[2]) `mov al, [ebx]` -> array[2] value save to al ``` Exists Out Program mov eax, 1 ; (sys_exit) int 0x80 ; Run System Call ``` ## ECX (Counter Register) Usages 1.Counter 2.Buffer ``` section .data array db 10, 20, 30, 40, 50 // Array -> base Address section .bss sum resd 1 // sum ->refernece ``` ``` section .data array db 10, 20, 30, 40, 50 ; Array section .bss ;Variable = Undifined sum resd 1 ; Assign 4 byte Memory Space for result section .text global _start _start: ; setting Counter & accumulator mov ecx, 5 ; setting Counter ! xor eax, eax ; clear accumulator mov ebx, array ; Mov Array Address to ebx loop_start: mov al, [ebx] ; mov Ebx Value to Al Register add eax, al ; *array[i] -> eax add ebx, 1 ; Array[i+1] loop loop_start ; ecx -1 -> cmp ecx,0 -> jpg loop_start ;mov accumlator value to sum mov [sum], eax ; Exit Sys call mov eax, 1 int 0x80 ``` loop loop_start -> ecx 中counter值會自動 -1 ### EDX 1. edx -> systems call (ntdll) 2. I/O Operation 3. Message length ## Pointer ### EIP Instruction Pointer Location of Execution This pointer value is Changed by Jump operation ### EBP (Base Pointer) Bottom of function ### ESP (Stack Pointer) Top of function # global global keyword usually is used to identifier accessible to the linker global _Start Linux ELF 可執行檔 預設會從 _start 這個標籤開始執行。 global 讓 _start 變成 可被連結器識別的符號,確保執行時會從這裡開始。 _start -> Main Function # Section ## .bss Defined not initial global variable. ``` section .bss byte_var resb 1 -> 1 byte word_var resw 1 -> 2 byte dword_var resd 1 -> 4 byte qword_var resq 1 -> 8 byte ``` 一個 word -> myWord dw 0x1234 ; //dw -> defined word ## .text (Read Only) 程式碼定義程式碼段(code segment),所有執行指令都應該放在 .text 段內。 This section is used to place all instructions ## .data This section is used to defined the variable ``` db "string" db 0xFF db 10 ;1 byte dw 1000 ;2 byte /double dd 10000l ;4 byte - 32bit / double double ``` # Instructions ## lea (Load Effective Address) LEA(Load Effective Address,載入有效位址)主要用來 計算記憶體位址 並將結果存入寄存器,而不會實際讀取記憶體的Value。 ``` mov ebx, 10 lea eax, [ebx] ; 計算 `ebx` 的位址並存入 `eax` ``` ## cmp (compare) According the compare result, it will set the flag in the background. cmp arg1, arg2 -> sub arg1,arg2 if arg1 = 1, arg2 = 3 cmp arg1,arg2 > flag = -2 ## jmp (jump) Comparing instruction usually follow the jump instruction. jump addr eip = addr ```(work) section .text global _start _start: mov ebx,42; Exit Code = 42 mov eax,1 ;Systems Exit Call jmp skip ; jump to skip label mov ebx,13; Exit Code = 13 skip: int 0x80 ``` ``` nasm -f elf32 ex3.asm -o ex3.o ld -m elf_i386 ex3.o -o ex3 ./ex3 echo $? OutPut:42 ``` ### Conditional Branching ``` je ;cmp a,b -> = jne ;cmp a,b -> != jl ; < jg ; > jle ; <= jge ; >= ``` ```(work) section .text global _start _start: mov ecx, 50 ; set the value to test jl instruction mov ebx,42; Exit Code = 42 mov eax,1 ;Systems Exit Call cmp ecx,100 ; 50 - 100 < 0 jl skip ; jump to skip label -> Check Flag! mov ebx,13; Exit Code = 13 skip: int 0x80 ``` ```result Output:42 ``` ### Loop ```(work) section .text global _start _start: mov ebx, 1 ;start ebx at 1 mov ecx, 4 ;number of interaction loop: add ebx,ebx ;power operation dec ecx ; dec -= 1 cmp ecx,0 jg loop mov eax,1 int 0x80 ``` Result ``` echo $? Output: 16 -> 1+1 , 2+2 , 4+4, 8+8 ``` ## mul multiplies ebx into eax ``` mul ebx ; eax *= ebx ``` ## div divides div edx ## dec decrease -> A -= 1 ### Type of jump je (jump equal to) jne (jump not equal to) jg (jump grate then) ## int 0x80 "int" witch is performed interrupt int 0x80 is used to interrupt the handler for systems call -> Step 1 CUP Jump to (Interrupt Vector Table, IVT) Step 2 Look for interrupt number # Stack View ## Push ![image](https://hackmd.io/_uploads/Hk0AQgGY1l.png) ```(work) ;push Pperation section .text global _start _start: sub esp,5 mov [esp], byte "M" mov [esp+1], byte "E" mov [esp+2], byte "O" mov [esp+3], byte "W" mov [esp+4], byte 10 ;Ascll \n mov eax,4 mov ebx,1 mov ecx,esp mov edx,5 int 0x80 mov eax,1 mov ebx,0 int 0x80 ``` ```(work) ais3@ais3:~/Desktop/genymotion/assemblyX86$ ld -m elf_i386 stack.o -o stack ais3@ais3:~/Desktop/genymotion/assemblyX86$ ./stack MEOW ``` ## PoP ``` pop eax -> assign Value to EAX from top of stack (Low Address) equal mov eax, dword [esp] add esp, 4 ``` 2025/2/6 ## Call (invoice Func 1.Push EIP to Stack (Push Return Address to Current ESP location) 2.Jump to Target label ```() Call func Hide Operation -> push 0x08048065 ; Return Addres Push to Stack -> jmp func ; jump to func Address ``` ```(work) global _start _start: ;if 0x0x08048060 call func ;5byte mov eax,1 ;0x08048065 int 0x80 func: mov ebx,42 pop eax ;0x08048065 -> eax jmp eax ``` ``` ais3@ais3:~/Desktop/genymotion/assemblyX86$ nasm -f elf32 callFun.asm -o callFun.o ais3@ais3:~/Desktop/genymotion/assemblyX86$ ld -m elf_i386 callFun.o -o callFun ais3@ais3:~/Desktop/genymotion/assemblyX86$ ./callFun ais3@ais3:~/Desktop/genymotion/assemblyX86$ echo $? 42 ``` ### Ret (Address Return) ```(work) global _start _start: call func mov eax,1 int 0x80 func: mov ebx,42 ret ``` ``` ais3@ais3:~/Desktop/genymotion/assemblyX86$ nasm -f elf32 callFun.asm -o callFun.o ais3@ais3:~/Desktop/genymotion/assemblyX86$ ld -m elf_i386 callFun.o -o callFun ais3@ais3:~/Desktop/genymotion/assemblyX86$ ./callFun ais3@ais3:~/Desktop/genymotion/assemblyX86$ echo $? 42 ``` # Alter the string of content in the Runtime ```(Work) section .data addr db "AeowHackel",0x0A section .text global _start _start: mov [addr], byte 'M' ;Alter char by the address mov [addr+9], byte 'r';Alter Char by the address offset mov eax,4 ; write SystemCall mov ebx,1 mov ecx,addr mov edx,12 int 0x80 ;Graceful Exit mov eax,1 mov ebx,0 int 0x80 ``` ```(work) OutPut: Meowhecker ``` # Preserver the stack using register (Stack) ```(work) ;Preserver the ESP by Usting Regitser section .text global _start _start: call func mov eax, 1 mov ebx, 0 ;return 0 Status Code int 0x80 func: mov ebp,esp ;perserver the ESP (return Address ) sub esp,5 mov [esp], byte "M" mov [esp+1], byte "E" mov [esp+2], byte "O" mov [esp+3], byte "W" mov [esp+4], byte 0x0a mov eax,4 mov ebx, 1 mov ecx, esp mov edx, 5 int 0x80 mov esp,ebp ret ;jump to ESP Address (Func Return Address ) ``` ## Prologue + Epilogue Common Usage Ensure the EBP Address is Correct (It's not changed by storing the ESP Address ) Prologue (Head) ``` func: push ebp mov ebp,esp sub esp,5 ;Mov Stack point to UPPPPPPPPPPPP ``` Epilogue (foot) ```(work) mov esp,ebp pop ebp ret ;jum to sep address () ``` Complete Code ```(work) ; Common Technique section .text: global _start _start: call func ; Push the EIP Address(Next Instruction Address) to Stack mov eax, 1 mov ebx, 0 int 0x80 func: push ebp mov ebp,esp sub esp,5 mov [esp], byte "M" mov [esp+1], byte "E" mov [esp+2], byte "O" mov [esp+3], byte "W" mov [esp+4], byte 0x0a ;syscall write mov eax,4 mov ebx, 1 mov ecx, esp mov edx, 5 int 0x80 ;return Original Address mov esp,ebp pop ebp ret ;jum to sep address () ``` ``` ais3@ais3:~/Desktop/genymotion/assemblyX86$ nasm -f elf32 callFun3PreservingStack.asm -o callFun3PreservingStack.o ais3@ais3:~/Desktop/genymotion/assemblyX86$ ld -m elf_i386 callFun3PreservingStack.o -o callFun3PreservingStack ais3@ais3:~/Desktop/genymotion/assemblyX86$ ./callFun3PreservingStack MEOW ``` # Handle the Return value From Functions Passing the value to function and interact with external Code ```(work) section .text global _start _start: push 10 ; Passing the args to func call func ; Push EIP Address to Stack | jum to func label mov ebx,eax mov eax, 1 ;syst Exit int 0x80 ; Call System Call func: push ebp ; Save EPB to Stack mov ebp, esp ; mov eax, [ebp + 8] ; passing 10 to eax Register (Cross the Return Address!) add eax,eax ;multiply the argument by two mov esp,ebp ;Recover ESP Address pop ebp; Recover EBP ----> Sub Current Address 4 byte back to the Return Address ret ; return form func (-> ESP) ``` ```(Resutl) ais3@ais3:~/Desktop/genymotion/assemblyX86$ nasm -f elf32 callCfunction.asm -o callCfunction.o ais3@ais3:~/Desktop/genymotion/assemblyX86$ ld -m elf_i386 callCfunction.o -o callCfunction ais3@ais3:~/Desktop/genymotion/assemblyX86$ ./callCfunction ais3@ais3:~/Desktop/genymotion/assemblyX86$ echo $? 20 ``` ## Using Printf function form C language! Using GCC as linker. instead of LD program. GCC link C Stander Library ``` ``` ------------------------------------- # Video https://www.youtube.com/watch?v=HgEGAaYdABA 0xA -> new Line db -> defined Byte ![image](https://hackmd.io/_uploads/HJjcI-C_Je.png) ## UNIX standard This's a header file that defined the systems call number for 32-bit program running on the 64-bit systems /usr/include/x86_64-linux-gnu/asm/unistd_32.h ![image](https://hackmd.io/_uploads/H1F2YWytJx.png) ``` section .data message: db "meowhecker", 0xA #declare message var message-length equ $-message In C language char message[]="meowhecker\n" ``` "$" -> Variable End Position(address) $ - message(Initial Address) EAX -> Function Return ``` echo "Hello, world!" > test.txt # 預設使用 FD=1(標準輸出),寫入 test.txt cat < test.txt # 使用 FD=0(標準輸入),從 test.txt 讀取 ls non_existing_file 2> error.log # 將錯誤(FD=2)導向到 error.log ``` ![image](https://hackmd.io/_uploads/Sy_cvHJF1l.png) ``` man 1 write 會顯示 Linux write 指令(命令行工具)。 man 2 write 會顯示 write 系統呼叫(syscall)。 ``` int 0x80 -> Systems interrupt for Running the systems call ### Gracefully Exit ! ``` #define __NR_exit 1 mov eax, 0x1; mov ebx, 0 ; If move the zero the main function that meam successfuly ``` ### Compile Assembly to Object Code ``` nasm Invoke NASM Assembler -f elf32 指定輸出格式為 ELF 32-bit(適用於 32 位 Linux) -o test.o 指定輸出的目標檔案名稱 (test.o) test.asm 要組譯的原始組合語言程式碼 ``` ```(work) ;include <unistd.h> ;ssize_t write(int fd, const void *buf, size_t count); global _start section .text _start: mov eax, 0x4 ;Using write systemCall mov ebx, 1 ;file Descriptor: Standard Output mov ecx, message mov edx, message_length int 0x80 ; System Interupt | Call the kernel ;Gracefully Exit mov eax, 1 ; exit system call xor ebx, ebx int 0x80 ; System Interupt | Call the kernel section .data message: db "meowhecker", 0xA message_length equ $-message ;Work !!!!!!!!!!! ``` ### Assembly to OB Code ``` nasm -f elf32 -o test1.o test1.asm ``` ### Links ld will pare _start and Assign the memory 符號(Symbol) 指的是 Variable Name、Function Name 、Program Entry point(_start) 等 Symbol = Variable Name, Function Name, _start, label... ``` ld -m elf_i386 -o test1 test1.o ``` ![image](https://hackmd.io/_uploads/B16K-LyYJl.png) 2025/2/4 Finish ! ### Square Bracket -> Dereference Operator [] -> *value (Access Memory Value) &value (Access Memory Address) ![image](https://hackmd.io/_uploads/rk6LUUyKJx.png) https://www.youtube.com/watch?v=75gBFiFtAb8&list=TLPQMDQwMjIwMjVdqgovRPxgIA&index=1 ### PLT functions The PLT (Procedure Linkage Table) is a mechanism used in ELF (Executable and Linkable Format) binaries to handle dynamic function calls Analysis Stack ![image](https://hackmd.io/_uploads/SJxplfulFJx.png) Push, PoP -> Operate Low Address Push -> ESP Print function ``` push message ; 4byte call printf ; 呼叫 printf,返回後 ESP point to message add esp, 4 ; 回收 4-byte memory Space ``` message 10 + 4 High Low push instructions -> Occupy 4 byte ``` objdump -d a.out | grep '<plt>' ``` --------------------------------------------- https://www.youtube.com/watch?v=wLXIWKUWpSs&list=PLmxT2pVYo5LB5EzTPZGfFN0c2GDiSXgQe&index=1 Eax2.asm ```(work) ; Output Meowhecker section .data message db "meowhecker", 0x0A length equ $ - message section .text global _start _start: ; Load the address of the message into the EAX register mov eax, 4 mov ebx, 1 mov ecx, message mov edx, length int 0x80 ; Exit the program with a status code of 0 mov eax, 1 xor ebx, ebx int 0x80 ``` # Assemble with NASM, Link with ld, and Execute ## Linker (ld) The linker will parse `_start` symbols and assign memory space. [symbols](symbols.md) ```sh # Check if the user provided an argument if [ -z "$1" ]; then # -z checks if $1 is an empty string echo "Usage: $0 <filename>" exit 1 fi FILE="$1" # Create directory if it doesn't exist mkdir -p $FILE # Move source file into the directory cp $FILE.asm ./$FILE/ || { echo "Error: Could not move $FILE.asm"; exit 1; } cd ./$FILE # Assemble with NASM nasm -f elf32 $FILE.asm -o $FILE.o || { echo "Error: NASM assembly failed"; exit 1; } # Link with ld ld -m elf_i386 $FILE.o -o $FILE || { echo "Error: Linking failed"; exit 1; } ./$FILE ``` ### Link with C Standard Library ```sh # Check if the user provided an argument if [ -z "$1" ]; then echo "Usage: $0 <filename>" exit 1 fi FILE="$1" # Create directory if it doesn't exist mkdir -p $FILE # Move source file into the directory cp $FILE.asm ./$FILE/ || { echo "Error: Could not move $FILE.asm"; exit 1; } cd ./$FILE # Assemble with NASM nasm -f elf32 $FILE.asm -o $FILE.o || { echo "Error: NASM assembly failed"; exit 1; } # Link with GCC gcc -m32 $FILE.o -o $FILE || { echo "Error: GCC linking failed"; exit 1; } ./$FILE ``` # call-function-in-asm.md ## Call function in Assembly Creating a function in assembly that can be called from a C program. Assembly Function Code (`code.asm`): ```asm global add66 add66: push ebp mov ebp, esp mov eax, [ebp + 8] add eax, 66 ; Function return mov esp, ebp ; Restore ESP pop ebp ret ``` Assemble it to an object code: ```sh nasm -f elf32 callFunFromObjcode.asm -o callFunFromObjcode.o ``` ### Defined Header File `callFunFromObjcode.h`: ```c int add66(int x); ``` ### C main function `main.c`: ```c #include <stdio.h> #include "callFunFromObjcode.h" int main() { int result; result = add66(20); printf("The sum of 66 and 20 is: %d\n", result); return 0; } ``` Linking the library: ```sh gcc -m32 callFunFromObjcode.o main.c -o callFunFromObjcode ./callFunFromObjcode ``` Output: ```sh ./callFunFromObjcode The sum of 66 and 20 is: 86 ``` # function.md ## Function and Procedure Analysis Example assembly function: ```asm global main addTwo: add eax, ebx ret main: mov eax, 4 mov ebx, 6 call addTwo mov ebx, eax mov eax, 1 int 0x80 section .note.GNU-stack noalloc noexec nowrite ; Fix linker warning ``` More details [here](gdb-gnu-debugger.md). ## Aligning to 16 Bytes Before a Function Call In **System V ABI**, the stack pointer (ESP or RSP) must be aligned to 16 bytes before a function call. Example: ```asm global main extern printf section .data msg db "meowhecker %d", 0x0a, 0x00 ; String format section .text main: push ebp mov ebp, esp sub esp, 8 ; Align stack to 16 bytes push 666 ; Argument for printf push msg ; Argument for printf format string call printf ; Call printf add esp, 8 ; Clean up stack mov eax, 0 ; Return 0 mov esp, ebp pop ebp ret ``` Output: `meowhecker 666` For more info: - [Passing values](passing-value.md) - [Calling functions in asm](call-function-in-asm.md) # gdb-gnu-debugger.md ## GDB (GNU Debugger) ### Instructions Layout View: ```sh layout asm ``` Breakpoints: ```sh break <label> break main ``` Handling execution: ```sh run [arguments] r [arguments] stepi # Step one instruction at a time si # Short form of stepi info register | info register esp # Info on registers ``` Examining memory: ```sh x /[count][format] [address] x/x $esp # View 1 word (4 bytes) at ESP in hex x/4x $esp # View 4 words (16 bytes) from ESP in hex x/4x [address] ``` | `x` | Examine memory | |:-------|:--------------------------| | `/x` | Display in **hexadecimal**| | `$esp` | Show memory at **ESP** | # passing-value.md ## Passing values ```asm section .text global _start _start: push 10 call selfAddFunc mov ebx, eax mov eax, 1 int 0x80 selfAddFunc: push ebp mov ebp, esp mov eax, [ebp + 8] add eax, eax mov esp, ebp pop ebp ret ``` Output: ```sh echo $? 20 # Output result ``` ### Adding Two Numbers ```asm global main addTwo: push ebp mov ebp, esp mov ebx, [ebp + 8] mov eax, [ebp + 12] add eax, ebx mov esp, ebp pop ebp ret main: push 4 push 6 call addTwo mov ebx, eax mov eax, 1 int 0x80 section .note.GNU-stack noalloc noexec nowrite ; Fix linker warning ``` ### Analysis Function return address and stack frames. # preserve-stack.md ## Preserve Stack Maintain stack integrity and prevent stack corruption. Prologue & Epilogue: ```asm func: push ebp mov ebp, esp sub esp, 5 ; Allocating memory ... mov esp, ebp pop ebp ret ``` ### Example ```asm section .text global _start _start: call func mov eax, 1 xor ebx, ebx int 0x80 func: push ebp mov ebp, esp sub esp, 5 mov [esp], byte 'm' mov [esp + 1], byte 'e' mov [esp + 2], byte 'o' mov [esp + 3], byte 'w' mov [esp + 4], byte 0x0a mov eax, 4 mov ebx, 1 mov ecx, esp mov edx, 5 int 0x80 mov esp, ebp pop ebp ret ``` Output: `meow` ## Tools ### Dynamic Analysis Using [GDB (GNU Debugger)](gdb-gnu-debugger.md). # x86-32bit-architecture.md ## X86-32bit Architecture ![image](files\image_0.png) ### Sections Logical division of program memory layout: - [.bss](bss.md) - [.data](data.md) - [.text (Read Only)](text-read-only.md) ### Stack Refer to [Stack](stack.md). ### Heap Managed by `malloc/new` and `free/delete`. ### Stack Frame A stack frame is a portion of the stack memory. When a function is called, a new stack frame is pushed onto the stack. When the function returns, the stack frame is popped off. Refer [in-memory layout](https://gabrieletolomei.wordpress.com/miscellanea/operating-systems/in-memory-layout/). # x86-assembly.md ## X86-Assembly Refer to: - [X86-32bit Architecture](x86-32bit-architecture.md) - [Registers](registers.md) - [Instructions](instructions.md) ### More Topics - [System Call](system-call.md) - [Assemble with NASM & Link with ld & Execution](assemble-with-nasm-and-link-with-ld-and-execut.md) - [Tools](tools.md) Further reading: [Watch this YouTube series](https://www.youtube.com/watch?v=EEEYPCxQyB4&list=PL2EF13wm-hWCoj6tUBGUmrkJmH1972dBB&index=23)