← Back to Writeups
CUSTOMEasyReversing

chain (RE6)

XESXOR9/2/20263 min read
#reversing#custom#easy#scasb_length_decoding#segment_length_to_ascii#static_source_analysis

chain (RE6)

Platform: CUSTOM | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: N/A | **Author: XESXOR Techniques: scasb_length_decoding, segment_length_to_ascii, static_source_analysis

Summary

Walkthrough of the CUSTOM Reversing chain (RE6). Task: NASM x86 32-bit source validates a stdin password against a long 'a'-run/'|'-delimited data string using repne scasb. Solution: each flag byte equals the length of its '|'-separated segment (run

Description

Flag is the input that makes app say "All ok!"

A NASM x86 (BITS 32) source file chain.asm is provided. The program reads a password from stdin and validates it byte-by-byte against a large constant data string. The goal is to find the input that prints All ok!. The recovered input is the flag, submitted via POST flag to rev-kids20.forkbomb.ru.

Analysis

The relevant parts of chain.asm:

nasm
section .data
    dat db 'aaaa...a|aaaa...a|...'   ; runs of 'a' separated by '|'
    flg db "All ok!",0xa
    size equ 19
‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

section .bss
    passw resb 256

section .text
_start:
    mov eax, 3            ; sys_read
    mov ebx, 0            ; stdin
    mov ecx, passw
    mov edx, 256
    int 80h

    mov ebp, 0           ; index 0..18
    mov edi, dat
lop:
    mov al, '|'
    mov esi, edi         ; save start of segment
    repne scasb          ; scan ES:[EDI] for '|', advancing EDI past it
    mov edx, edi
    sub edx, esi         ; edx = bytes scanned = run_of_a + 1 ('|' counted)
    mov ecx, passw
    add ecx, ebp
    mov al, [ecx]        ; al = passw[ebp]
    cmp al, dl           ; compare to low byte of scanned length
    jnz fail
    inc ebp
    cmp ebp, size        ; loop 19 times
    jnz lop
    ; print "All ok!"

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

Key semantics of repne scasb:

  • It compares AL against ES:[EDI], then increments EDI, decrementing ECX, repeating until a match (ZF=1).
  • When it stops, EDI points one byte past the matched '|'.

So EDI_after - ESI_before equals the number of bytes consumed for this segment: the run of 'a' plus the trailing '|'. That value (its low byte dl) is compared against the input byte at index ebp.

Therefore each input byte must equal len(run_of_a) + 1 for the corresponding segment. The loop runs 19 times (size equ 19), so the flag is 19 bytes. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Solution

Split dat on '|' and, for each of the first 19 segments, compute len(segment) + 1 (the +1 accounts for the '|' that repne scasb counts), then convert to a character.

python
#!/usr/bin/env python3
import re

src = open('chain.asm').read()
dat = re.search(r"dat db '([^']*)'", src, re.S).group(1)
segs = dat.split('|')
chars = [len(s) + 1 for s in segs[:19]]   # +1 for the '|' counted by repne scasb
flag = ''.join(chr(c) for c in chars)
print(chars)
print(flag)

Output:

[102, 108, 97, 103, 123, 116, 104, 105, 115, 95, 119, 64, 115, 95, 101, 97, 115, 121, 125]
flag{REDACTED}

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

Feeding flag{REDACTED} on stdin makes the program print All ok!. ‍​‌‌​​‌​​​‌‌​​‌​​​​‌‌​‌​​​​‌‌‌​​‌​​‌‌​​​‌​​‌‌‌​​​​​‌‌​‌‌​​​‌‌​​​​‍

Key Takeaways / Lessons

  • Mastering scasb_length_decoding, segment_length_to_ascii, static_source_analysis was key to this challenge.
  • Always check for common misconfigurations and verify assumptions.

Crafted by XESXOR Research • 2026-06-15 • CUSTOM • chain (RE6) • Difficulty: Easy