chain (RE6)
chain (RE6)
Platform: rev_kids20 | Category: Reversing | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-06-15 | Status: Solved Techniques: scasb_length_decoding, segment_length_to_ascii, static_source_analysis
Summary
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 of 'a' plus the '|'), so split on '|' and take len(seg)+1 as ASCII.
chain (RE6) — rev_kids20
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 read-only • copy allowedsection .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
ALagainstES:[EDI], then incrementsEDI, decrementingECX, repeating until a match (ZF=1). - When it stops,
EDIpoints 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 read-only • copy allowed#!/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!.