Cybersecurity Notes
MathematicsCryptography
  • Cybersecurity Notes
  • Binary Exploitation
    • Stack
      • Introduction
      • ret2win
      • De Bruijn Sequences
      • Shellcode
      • NOPs
      • 32- vs 64-bit
      • No eXecute
      • Return-Oriented Programming
        • Calling Conventions
        • Gadgets
        • Exploiting Calling Conventions
        • ret2libc
        • Stack Alignment
      • Format String Bug
      • Stack Canaries
      • PIE
        • Pwntools, PIE and ROP
        • PIE Bypass with Given Leak
        • PIE Bypass
      • ASLR
        • ASLR Bypass with Given Leak
        • PLT and GOT
        • ret2plt ASLR bypass
      • GOT Overwrite
        • Exploiting a GOT overwrite
      • RELRO
      • Reliable Shellcode
        • ROP and Shellcode
        • Using RSP
        • ret2reg
          • Using ret2reg
      • One Gadgets and Malloc Hook
      • Syscalls
        • Exploitation with Syscalls
        • Sigreturn-Oriented Programming (SROP)
          • Using SROP
      • ret2dlresolve
        • Exploitation
      • ret2csu
        • Exploitation
        • CSU Hardening
      • Exploiting over Sockets
        • Exploit
        • Socat
      • Forking Processes
      • Stack Pivoting
        • Exploitation
          • pop rsp
          • leave
    • Heap
      • Introduction to the Heap
      • Chunks
      • Freeing Chunks and the Bins
        • Operations of the Fastbin
        • Operations of the Other Bins
      • Malloc State
      • malloc_consolidate()
      • Heap Overflow
        • heap0
        • heap1
      • Use-After-Free
      • Double-Free
        • Double-Free Protections
        • Double-Free Exploit
      • Unlink Exploit
      • The Tcache
        • Tcache: calloc()
        • Tcache Poisoning
      • Tcache Keys
      • Safe Linking
    • Kernel
      • Introduction
      • Writing a Char Module
        • An Interactive Char Driver
        • Interactivity with IOCTL
      • A Basic Kernel Interaction Challenge
      • Compiling, Customising and booting the Kernel
      • Double-Fetch
        • Double-Fetch without Sleep
      • The Ultimate Aim of Kernel Exploitation - Process Credentials
      • Kernel ROP - ret2usr
      • Debugging a Kernel Module
      • SMEP
        • Kernel ROP - Disabling SMEP
        • Kernel ROP - Privilege Escalation in Kernel Space
      • SMAP
      • modprobe_path
      • KASLR
      • KPTI
    • Browser Exploitation
      • *CTF 2019 - oob-v8
        • The Challenge
      • picoCTF 2021 - Kit Engine
      • picoCTF 2021 - Download Horsepower
  • Reverse Engineering
    • Strings in C++
    • C++ Decompilation Tricks
    • Reverse Engineering ARM
  • Blockchain
    • An Introduction to Blockchain
  • Smart Contracts and Solidity
  • Hosting a Testnet and Deploying a Contract
  • Interacting with Python
  • Writeups
    • Hack The Box
      • Linux Machines
        • Easy
          • Traceback
        • Medium
          • Magic
          • UpDown
        • Hard
          • Intense
      • Challenges
        • Web
          • Looking Glass
          • Sanitize
          • Baby Auth
          • Baby Website Rick
        • Pwn
          • Dream Diary: Chapter 1
            • Unlink Exploit
            • Chunk Overlap
          • Ropme
    • picoGym
      • Cryptography
        • Mod 26
        • Mind Your Ps and Qs
        • Easy Peasy
        • The Numbers
        • New Caesar
        • Mini RSA
        • Dachshund Attacks
        • No Padding, No Problem
        • Easy1
        • 13
        • Caesar
        • Pixelated
        • Basic-Mod1
        • Basic-Mod2
        • Credstuff
        • morse-code
        • rail-fence
        • Substitution0
        • Substitution1
        • Substitution2
        • Transposition-Trial
        • Vigenere
        • HideToSee
    • CTFs
      • Fword CTF 2020
        • Binary Exploitation
          • Molotov
        • Reversing
          • XO
      • X-MAS CTF 2020
        • Pwn
          • Do I Know You?
          • Naughty
        • Web
          • PHP Master
      • HTB CyberSanta 2021
        • Crypto
          • Common Mistake
          • Missing Reindeer
          • Xmas Spirit
          • Meet Me Halfway
  • Miscellaneous
    • pwntools
      • Introduction
      • Processes and Communication
      • Logging and Context
      • Packing
      • ELF
      • ROP
    • scanf Bypasses
    • Challenges in Containers
    • Using Z3
    • Cross-Compiling for arm32
Powered by GitBook
On this page

Was this helpful?

Export as PDF
  1. Writeups
  2. picoGym
  3. Cryptography

New Caesar

We found a brand new type of encryption, can you break the secret code? (Wrap with picoCTF{}) apbopjbobpnjpjnmnnnmnlnbamnpnononpnaaaamnlnkapndnkncamnpapncnbannaapncndnlnpna new_caesar.py

So we are given a script new_caesar.py, let's analyse it.

LOWERCASE_OFFSET = ord("a")
ALPHABET = string.ascii_lowercase[:16]

[...]

flag = "redacted"
key = "b"
assert all([k in ALPHABET for k in key])
assert len(key) == 1

b16 = b16_encode(flag)
enc = ""
for i, c in enumerate(b16):
	enc += shift(c, key[i % len(key)])
print(enc)

So first off we know that the ALPHABET is the first 16 letters in the lowercase alphabet. The key is one character long, and is also in ALPHABET. The flag has b16_encode() run on it, and every letter in the result of that is run under shift(). To reverse, it, we have to first undo shift() and then b16_encode().

def b16_encode(plain):
	enc = ""
	for c in plain:
		binary = "{0:08b}".format(ord(c))
		enc += ALPHABET[int(binary[:4], 2)]
		enc += ALPHABET[int(binary[4:], 2)]
	return enc

def shift(c, k):
	t1 = ord(c) - LOWERCASE_OFFSET
	t2 = ord(k) - LOWERCASE_OFFSET
	return ALPHABET[(t1 + t2) % len(ALPHABET)]

shift() is a very simple function, although the arithmetic looks a bit strange. t1 is actually the index of c in ALPHABET, as it grabs the character code and then subtracts off that of a. t2 is the same, but for the key. t2 is then added as a shift to t1 and the index in ALPHABET is returned, so it's essentially a Caesar with a shift dictated by k. We can undo this easily, by subtracting instead of adding:

def unshift(p, k):
    t1 = ord(p) - LOWERCASE_OFFSET
    t2 = ord(k) - LOWERCASE_OFFSET
    return ALPHABET[(t1 - t2) % len(ALPHABET)]

As for b16encode(), it calculates the 8-bit binary representation of the character code and then splits it into two 4-bit values, which are used as indices in ALPHABET. We can undo this too.

def b16_decode(enc):
    enc = [enc[x:x + 2] for x in range(0, len(enc), 2)]        # split into pairs
    dec = ''

    for pair in enc:
        bin1 = ALPHABET.index(pair[0])
        bin2 = ALPHABET.index(pair[1])
        combined = int(bin(bin1)[2:].zfill(4) + bin(bin2)[2:].zfill(4), 2)
        dec += chr(combined)

    return dec

The .zfill(4) ensures that each representation of the two values is 4 bits long, which is very important for parsing it as an 8-bit bniary value at the end!

We then just have to brute force for every possible key in ALPHABET, getting 16 possibilities:

ÐÒÓÛßÐ
ÈèËÌËÊÀûÎÍÍÎÏÿûÊÉþÂÉÁûÎþÁÀüÏþÁÂÊÎÏ
íü×üý·×º»º¹¿ê½¼¼½¾îê¹¸í±¸°ê½í°¿ë¾í°±¹½¾
ÜëÆëì¦Æ©ª©¨®Ù¬««¬­ÝÙ¨§Ü §¯Ù¬Ü¯®Ú­Ü¯ ¨¬­
ËÚµÚەµ˜™˜—È›šš›œÌȗ–ËŸ–žÈ›ËžÉœËžŸ—›œ
ºÉ¤Éʄ¤‡ˆ‡†Œ·Š‰‰Š‹»·†…ºŽ…·ŠºŒ¸‹ºŽ†Š‹
©¸“¸¹s“vwvu{¦yxxyzª¦ut©}t|¦y©|{§z©|}uyz
˜§‚§¨b‚efedj•hgghi™•dc˜lck•h˜kj–i˜kldhi
‡–q–—QqTUTSY„WVVWXˆ„SR‡[RZ„W‡ZY…X‡Z[SWX
v…`…†@`CDCBHsFEEFGwsBAvJAIsFvIHtGvIJBFG
et_tu?_23217b54456fb10e908b5e87c6e89156
TcNcd.N!"! &Q$##$%UQ /T(/'Q$T'&R%T'( $%
CR=RS=@D@C@CAC
?202
!001ûþÿþýó.ñððñò".ýü!õüô.ñ!ôó/ò!ôõýñò
/
/ ê
íîíìâàïïàáìëäëãàãâáãäìàá

Process finished with exit code 0

The only one that looks right is et_tu?_23217b54456fb10e908b5e87c6e89156 (given the title), and we submit that as the flag.

Full script:

import string

LOWERCASE_OFFSET = ord("a")
ALPHABET = string.ascii_lowercase[:16]


def unshift(p, k):
    t1 = ord(p) - LOWERCASE_OFFSET
    t2 = ord(k) - LOWERCASE_OFFSET
    return ALPHABET[(t1 - t2) % len(ALPHABET)]


def b16_decode(enc):
    enc = [enc[x:x + 2] for x in range(0, len(enc), 2)]
    dec = ''

    for pair in enc:
        bin1 = ALPHABET.index(pair[0])
        bin2 = ALPHABET.index(pair[1])
        combined = int(bin(bin1)[2:].zfill(4) + bin(bin2)[2:].zfill(4), 2)
        dec += chr(combined)

    return dec


enc_flag = 'apbopjbobpnjpjnmnnnmnlnbamnpnononpnaaaamnlnkapndnkncamnpapncnbannaapncndnlnpna'

for key in ALPHABET:
    shifted_flag = ''

    for i, p in enumerate(enc_flag):
        shifted_flag += unshift(p, key)

    d = b16_decode(shifted_flag)

    print(d)

# picoCTF{et_tu?_23217b54456fb10e908b5e87c6e89156}

Last updated 4 months ago

Was this helpful?