Overview
Players get two 32-character strings pulled out of NetBIOS name registration traffic. They aren’t hostnames, and they aren’t hex either. NetBIOS names get mangled before they go on the wire by RFC 1001 first-level encoding, and undoing that gives back two names that read as the flag.
Background
NetBIOS names are always 16 bytes. Fifteen of those are the name, space-padded if it’s shorter, and the sixteenth is a suffix byte identifying which service registered it. 0x00 is the Workstation Service, 0x20 is the File Server Service, 0x1B is a Domain Master Browser, 0x1E is a browser election. So a host calling itself WORKSTATION actually registers WORKSTATION \x00, four spaces and all.
Those bytes can’t be sent as-is. NBNS is built on the DNS packet format, and a NetBIOS name will happily contain things a DNS label can’t hold: spaces, control characters, that null suffix. RFC 1001 works around it with first-level encoding. Split each byte into its two nibbles, add 0x41 (A) to each one, and you get two printable characters per byte. Sixteen bytes in, a 32-character label out.
There’s a side effect that gives the whole thing away. A nibble is 0 through 15, so A + nibble can only ever produce A through P. No digits, nothing past P, ever.
Reconnaissance
The two names as observed:
FDGLGJGMGMECGJHEHLGODDHEGCGJDAAA
HDFPGEGDDAGEGFFPHEDAFPHHDBGOHNAA
Both 32 characters, all letters. Hex is the obvious first guess and it’s wrong immediately, since hex stops at F and there’s a G in the second position of the first string. Base32 survives slightly longer but not much: its alphabet runs the full A to Z, and neither string has a single character past P.
Sixteen possible symbols starting at A, in a string that’s exactly 32 long. One nibble per character, 16 bytes total, which happens to be the exact width of a NetBIOS name.
Exploitation
Take the characters in pairs, subtract A from each, glue the two nibbles back into a byte. By hand, the first name starts FD GL GJ GM GM EC, which is 5,3 6,11 6,9 6,12 6,12 4,2, which is 0x53 0x6B 0x69 0x6C 0x6C 0x42, which is SkillB. Good enough to stop checking and write the loop.
Two details fall out once both names are fully decoded. Neither one has any space padding, because all 15 name bytes are used up by flag content. A shorter name would have trailed off in repeated CA pairs, 0x20 being a space. And both names end in AA, or 0x00, the Workstation Service suffix. The challenge saying these came from workstations isn’t just set dressing, it’s in the packets.
Getting the Flag
The quickest route is CyberChef’s built-in Decode NetBIOS Name operation, which does the first-level decode natively — drop it on the recipe, leave the offset at its default of 65 ('A'), and paste either name in:
Input: FDGLGJGMGMECGJHEHLGODDHEGCGJDAAA
Recipe: Decode NetBIOS Name (Offset 65)
Output: SkillBit{n3tbi0
Run it on the second name too and concatenate. The trailing null suffix comes through as an unprintable byte you can ignore. That’s the whole solve for anyone who recognises the encoding.
To do it from scratch instead, decode both, drop the suffix byte, and join them in capture order:
python3 -c '
names = ["FDGLGJGMGMECGJHEHLGODDHEGCGJDAAA",
"HDFPGEGDDAGEGFFPHEDAFPHHDBGOHNAA"]
for n in names:
b = bytes(((ord(n[i]) - 65) << 4) | (ord(n[i+1]) - 65) for i in range(0, 32, 2))
print(f"{b!r} suffix=0x{b[15]:02x}")
print("".join(
bytes(((ord(n[i]) - 65) << 4) | (ord(n[i+1]) - 65) for i in range(0, 30, 2)).decode()
for n in names))
'
b'SkillBit{n3tbi0\x00' suffix=0x00
b's_dc0de_t0_w1n}\x00' suffix=0x00
SkillBit{n3tbi0s_dc0de_t0_w1n}
Printing the raw names first is worth the extra line. Readable ASCII instead of garbage means the encoding guess was right, and the two 0x00 suffixes confirm both hosts registered as workstations.
SkillBit{REDACTED}
Key Takeaways
* NetBIOS names aren’t plaintext on the wire. A 32-character label that never goes past P is first-level encoding, and spotting an encoding by its alphabet beats guessing at it.
* That last byte is a service suffix, not part of the name. It tells you what the host was advertising itself as.
* Wireshark decodes all of this for you in nbns.name, so a capture would just hand over the answer. Knowing the transform matters when all you’ve got is a log line or an alert.
* NBNS is unauthenticated and broadcast-based, which is the entire reason Responder-style LLMNR/NBT-NS poisoning works as well as it does. Turn NetBIOS over TCP/IP off wherever nothing still depends on it.