← Back to Writeups
CUSTOMEasyReversing

ASM1 (RE6_ASM_1)

XESXOR9/10/20262 min read
#reversing#custom#easy#manual_register_tracing#x86_div_mul_semantics#linux

ASM1 (RE6_ASM_1)

Platform: rev_kids20 | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: Linux | Author: XESXOR | Date: 2026-06-13 | Status: Solved Techniques: manual_register_tracing, x86_div_mul_semantics

Summary

Task: given a short x86 NASM snippet (asm_1.s), compute the final value of eax. Solution: hand-trace the registers, applying x86 div (EDX:EAX / r32 -> quotient EAX, remainder EDX) and mul (EDX:EAX = EAX * r32) semantics; remainder 10 squared gives eax = REDACTED.

ASM1 (RE6_ASM_1) — rev_kids20

Description

Given the x86 NASM source asm_1.s. Answer: eax = ? Platform: rev-kids20.forkbomb.ru — Author: Timofey Milovanov (tmilovanov) Submitted via POST field flag.

A beginner reverse task: statically trace a 6-instruction x86 snippet and report the final value of register eax.

Analysis

Source (asm_1.s):

nasm
xor edx, edx     ; edx = 0
mov eax, 0x64    ; eax = 0x64
mov ebx, 30      ; ebx = 30
div ebx          ; unsigned divide EDX:EAX by ebx
mov eax, edx     ; eax = remainder
mul edx          ; EDX:EAX = eax * edx

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

The two traps are the x86 div/mul semantics:

  • div r/m32 divides the 64-bit dividend EDX:EAX by the operand. Quotient goes to EAX, remainder goes to EDX. EDX must be initialized (here xor edx, edx clears it so the dividend is just 0x64).
  • mul r/m32 computes EDX:EAX = EAX * operand (unsigned). The high dword lands in EDX, the low dword (the answer we care about) in EAX.

Solution

Hand-trace the registers:

  1. xor edx, edx → edx = 0
  2. mov eax, 0x64 → eax = 0x64
  3. mov ebx, 30 → ebx = 30
  4. div ebx → dividend EDX:EAX = 0x0_00000064, divisor 30:
    • quotient eax = 0x64 / 30 = 3
    • remainder edx = 0x64 % 30 = 10
  5. mov eax, edx → eax = 10 (the remainder)
  6. mul edx → EDX:EAX = eax * edx = 10 * 10 = 0x64, so eax = 0x64, edx = 0 ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Final eax = REDACTED.

Verify with an actual CPU if desired:

bash
cat > /tmp/asm1.s <<'EOF'
section .text
global _start
_start:
    xor edx, edx
    mov eax, 0x64
    mov ebx, 30
    div ebx
    mov eax, edx
    mul edx
    ; eax now holds the answer; pass it as exit code
    mov ebx, eax
    mov eax, 1
    int 0x80
EOF
nasm -f elf32 /tmp/asm1.s -o /tmp/asm1.o && ld -m elf_i386 /tmp/asm1.o -o /tmp/asm1
/tmp/asm1; echo "eax = $?"   # -> eax = REDACTED

‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍