← Back to Writeups
CUSTOMEasyCrypto

Base100 (Emoji Encoding)

XESXOR9/10/20264 min read
#crypto#custom#easy#base100_decode#brute_force_offset#codepoint_offset#emoji_decode

Base100 (Emoji Encoding)

Platform: taipanbyte | Category: Crypto | Type: Challenge | Difficulty: Easy | OS: NA | Author: XESXOR | Date: 2026-02-14 | Status: Solved Techniques: base100_decode, brute_force_offset, codepoint_offset, emoji_decode

Summary

Task: Decode an all-emoji encoded message. Solution: Identify Base100 encoding by analyzing emoji codepoint range (U+1F427-U+1F474), find the decoding formula ASCII = codepoint - 0x1F427 + 48 by matching the flag prefix, and decode the task name as a self-referential "Base100" hint.

Base100 (Emoji Encoding) β€” TaipanByte CTF

Description

The task name and description were both encoded entirely in emoji:

  • Task name: πŸΉπŸ‘˜πŸ‘ͺπŸ‘œπŸ¨πŸ§πŸ§
  • Description: πŸ‘‹πŸΉπŸ‘²πŸ‘„πŸΌπŸ‘†πŸ‘ŽπŸ‘–πŸ‘„πŸΌπŸ‘†πŸ‘ŽπŸ‘–πŸΌπŸ‘€πŸ§πŸ‘‘πŸ‘ πŸ‘–πŸ‘πŸ‘£πŸ·πŸ‘žπŸ‘΄

Flag format: TB{...}

Analysis

  1. Both the task name and description consist entirely of emoji characters
  2. All emoji fall in a narrow Unicode range: U+1F427 (🐧) to U+1F474 (πŸ‘΄)
  3. There are 21 unique emoji across both strings
  4. The narrow range suggests a simple offset-based encoding β€” each emoji maps to one ASCII character
  5. The key insight: the task name itself is the hint. Once decoded, it reads "Base100" β€” a known encoding scheme that maps ASCII to emoji β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

Codepoint Mapping

EmojiCodepointOffset from U+1F427+ 48 (ASCII '0')Character
🐧U+1F4270480
🐨U+1F4281491
🐹U+1F4391866B
πŸ‘‹U+1F44B3684T
πŸ‘„U+1F4442977M
🐼U+1F43C2169E
πŸ‘†U+1F4463179O
πŸ‘ŽU+1F44E3987W
πŸ‘–U+1F4564795_
πŸ‘²U+1F47275123{
πŸ‘΄U+1F47477125}
β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

Decoding Formula

ASCII_char = chr(ord(emoji) - 0x1F427 + 48)

Where:

  • 0x1F427 (🐧) is the base emoji codepoint (minimum in the set)
  • 48 is the ASCII code for '0' β€” the offset that makes the mapping produce readable text

Approach: Offset Brute-Force

Since the encoding is a simple linear mapping emoji -> ASCII, the approach was:

  1. Find the minimum codepoint in the emoji set: U+1F427 (🐧)
  2. Compute offsets from this base for each emoji
  3. Try adding common ASCII base values (0, 32, 48, 65, 97) to the offsets
  4. With base 48 (ASCII '0'), the title decoded to "Base100" β€” confirming the scheme
  5. Apply the same formula to the description to get the flag β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

Solution

python
#!/usr/bin/env python3
"""
TaipanByte CTF β€” Base100 Emoji Decoder
Decodes emoji-encoded text using codepoint offset arithmetic.
"""

title = "πŸΉπŸ‘˜πŸ‘ͺπŸ‘œπŸ¨πŸ§πŸ§"
description = "πŸ‘‹πŸΉπŸ‘²πŸ‘„πŸΌπŸ‘†πŸ‘ŽπŸ‘–πŸ‘„πŸΌπŸ‘†πŸ‘ŽπŸ‘–πŸΌπŸ‘€πŸ§πŸ‘‘πŸ‘ πŸ‘–πŸ‘πŸ‘£πŸ·πŸ‘žπŸ‘΄"

# Base100 encoding parameters
BASE_EMOJI = 0x1F427  # 🐧 - minimum codepoint in the set
ASCII_OFFSET = 48      # ASCII '0' - makes the mapping produce readable text

def decode_base100(encoded: str) -> str:
    """Decode Base100 emoji string to ASCII."""
    return ''.join(chr(ord(c) - BASE_EMOJI + ASCII_OFFSET) for c in encoded)
β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

# Decode
title_decoded = decode_base100(title)
flag = decode_base100(description)

print(f"Title: {title_decoded}")   # Base100
print(f"Flag:  {flag}")            # TB{REDACTED}

# Verification: brute-force approach to find the correct offset
print("\n--- Brute-force offset search ---")
base = min(ord(c) for c in title + description)
for offset in [0, 32, 48, 65, 97]:
    decoded = ''.join(chr(ord(c) - base + offset) for c in title)
    print(f"  offset={offset:3d}: {decoded}")

Step-by-step Decoding of the Description

β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

πŸ‘‹ β†’ U+1F44B β†’ 0x1F44B - 0x1F427 + 48 = 36 + 48 = 84  β†’ 'T'
🐹 β†’ U+1F439 β†’ 0x1F439 - 0x1F427 + 48 = 18 + 48 = 66  β†’ 'B'
πŸ‘² β†’ U+1F472 β†’ 0x1F472 - 0x1F427 + 48 = 75 + 48 = 123 β†’ '{'
πŸ‘„ β†’ U+1F444 β†’ 0x1F444 - 0x1F427 + 48 = 29 + 48 = 77  β†’ 'M'
🐼 β†’ U+1F43C β†’ 0x1F43C - 0x1F427 + 48 = 21 + 48 = 69  β†’ 'E'
πŸ‘† β†’ U+1F446 β†’ 0x1F446 - 0x1F427 + 48 = 31 + 48 = 79  β†’ 'O'
πŸ‘Ž β†’ U+1F44E β†’ 0x1F44E - 0x1F427 + 48 = 39 + 48 = 87  β†’ 'W'
πŸ‘– β†’ U+1F456 β†’ 0x1F456 - 0x1F427 + 48 = 47 + 48 = 95  β†’ '_'
πŸ‘„ β†’ 'M'  🐼 β†’ 'E'  πŸ‘† β†’ 'O'  πŸ‘Ž β†’ 'W'  πŸ‘– β†’ '_'
🐼 β†’ 'E'  πŸ‘€ β†’ 'm'  🐧 β†’ '0'  πŸ‘‘ β†’ 'j'  πŸ‘  β†’ 'i'  πŸ‘– β†’ '_'
πŸ‘ β†’ 'f'  πŸ‘£ β†’ 'l'  🐷 β†’ '@'  πŸ‘ž β†’ 'g'  πŸ‘΄ β†’ '}'
β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€

Result: TB{REDACTED}

Notes

  • Base100 (also known as "emoji encoding") is a real encoding scheme that maps ASCII bytes to emoji
  • The specific variant here uses base codepoint U+1F427 with ASCII offset 48
  • Other Base100 implementations may use different base codepoints (e.g., U+1F600)
  • The approach of trying multiple ASCII offsets against emoji codepoints is a reliable general strategy for unknown emoji encodings β€β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€‹β€‹β€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€‹β€‹β€Œβ€Œβ€Œβ€‹β€‹β€‹β€‹β€‹β€Œβ€Œβ€‹β€Œβ€Œβ€‹β€‹β€‹β€Œβ€Œβ€‹β€‹β€‹β€‹β€