LoginSignup
2
2

More than 3 years have passed since last update.

Base64デコーダーを作る

Posted at

Base64デコーダーを作る

とあるCrackmeでcustom_base64なるものでエンコードされた文字列が出てきた...

Flagを手に入れるためにはこれをデコードして元の文字列を見つけなきゃいけない.
custom_base64とはなんなのか...答えを見つけるために,我々はアマゾンの奥地へと...

概要

Base64の仕組みの中で000000 ~ 111111を文字に置き換えた辞書が存在する.
通常のBase64では順番に ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/ をあてはめた辞書が使われている.
これを指定した辞書に入れ替えたものがcustom_base64関数の中身であった.
Base64を実装する記事を参考に本記事ではPythonでデコーダーを実装する.

Base64の仕組み

エンコード

大まかにBase64のエンコードの処理を確認します.詳しくは他サイトを参照.

  1. 変更したい文字列(ASCII)をバイナリ(2進数)に変換
  2. バイナリを6bitづつに分割
  3. 分割した際に最後が6bitより少なくなるため,6bitになるように0を追加する
  4. 変換表を用いて6bitを文字に変換
  5. 4biteずつBase64では出力するために文字数が4の倍数文字になるよう"="を付け足す
  6. base64の文字列の完成!!

デコード

エンコードの仕組みがわかればデコードは簡単!基本的には逆の手順を踏むだけ!

  1. 付け足された"="を削除
    • SG9nZUhvZ2U=SG9nZUhvZ2U
  2. 変換表を用いて文字をバイナリに変換してつなげる.
    • SG9nZUhvZ2U010010 000110 111101 100111 011001 010100 100001 101111 011001 110110 010100
  3. バイナリを8bitずつに分割,エンコード3. で付け足された0が余るのでそれらを削除
    • 01001000 01101111 01100111 01100101 01001000 01101111 01100111 01100101 00
  4. 2進数bitをASCIIに変換
01001000 → H
01101111 → o
01100111 → g
01100101 → e
01001000 → H
01101111 → o
01100111 → g
01100101 → e
  1. デコード完了!

プログラムにしてみる

custom_base64_decoder.py
import sys
import argparse
BYTE_SIZE = 8

# 000000 -> 111111まで1文字ずつ辞書型リストを作成する関数
def makeDict(base64Dict_seed):
    dictionary = {}

    for i in range(0, 64):
        dictionary[format(i, '06b')] = base64Dict_seed[i]

    return dictionary


# 文字列s をn文字で区切ってリスト化する関数
def split(string, n):
    split_list = []

    for i in range(0, len(string), n):
        split_list.append(string[i:i+n])

    return split_list


# 文字列がn文字なかったらn文字になるように`c`を足す
def fillBlank(s, n, c):
    mod = len(s) % n

    if mod == 0:
        return s
    else:
        margin = n - mod
        return s + c * margin


# 辞書の値を渡すと辞書のキーを返す
def getValue(key, items):
    for v in items.items():
        # print(v[1])
        if v[1] == key:
            # print(v)
            return v[0]
    return ''


def main():
    # -kをつけるとカスタム辞書を入力できる
    parser = argparse.ArgumentParser(
    description='custom Base64 Decoder')
    parser.add_argument('-k', '--key', help="Use custom Seed to encrypt in base64 ", \
        default="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/")
    parser.add_argument('text', help='base text')
    args = parser.parse_args()


    # 0. 辞書を作る
    base64Dict = makeDict(args.key)


    # 1. '='をはずす
    text = args.text.replace("=", '')

    binStr = ""


    # 2. 変換表を用いて文字をバイナリに変換してつなげる.
    for i in text:
        binStr += getValue(i, base64Dict)

    # 3. バイナリを8bitずつに分割,エンコード3. で付け足された0が余るのでそれらを削除
    splitCount = 8
    s = split(binStr, splitCount)

    if (len(s[-1]) != 8):
        s.pop(-1)


    # 4. 2進数bitをASCIIに変換
    result =""

    for c in s:
        print(c + " → " + chr(int(c, 2)))
        result += chr(int(c, 2))

    print(result)

if __name__ == "__main__":
    main()

使い方

$ python3 customBase64Decoder.py <Base64テキスト>
$ python3 customBase64Decoder.py -k <Custom辞書> <Base64テキスト>
$ python3 customBase64Decoder.py SG9nZUhvZ2U=
$ python3 customBase64Decoder.py -k xEPOKnvADqeG0m1VkZ47CM653jrtbzLsTc2ypoYUSWJ9ludQig+awf8XF/RNHBhI 4vBUjCcQj8C=

HogeHoge

まとめ

Base64完全に理解した.
これでオリジナルBase64つくって秘密の通信ができちゃうね,やったね

サンプルコードはGitHubに置いてあります

参考文献

base64ってなんぞ??理解のために実装してみた - qiita
https://qiita.com/PlanetMeron/items/2905e2d0aa7fe46a36d4

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2