TWCTF 5TH 2019 Crypto Writeup(+2) Crypto道場[2/100]

おひさしぶりです。duckです。
最近全くCTFをやっていないのでCrypto道場と題してCrypt100題解くまで頑張る会やります。
解説は最小限にするので、わからないところはコメントいただければ気が付き次第対応します。
応援よろしく!

さて記念すべき最初の問題は
今週末に行われたTWCTFから2題解いたのでそこから。

1.real-baby-rsa
 与えられたのはcodeとoutputファイル。

flag = 'TWCTF{CENSORED}'
# Public Parameters
N = 36239973541558932215768154398027510542999295460598793991863043974317503405132258743580804101986195705838099875086956063357178601077684772324064096356684008573295186622116931603804539480260180369510754948354952843990891989516977978839158915835381010468654190434058825525303974958222956513586121683284362090515808508044283236502801777575604829177236616682941566165356433922623572630453807517714014758581695760621278985339321003215237271785789328502527807304614754314937458797885837846005142762002103727753034387997014140695908371141458803486809615038309524628617159265412467046813293232560959236865127539835290549091
e = 65537

# Encrypt the flag!
for char in flag:
    print(pow(ord(char), e, N))

output
Dropbox - output - Simplify your life
code
Dropbox - problem.py - Simplify your life


flagとして使われる文字列を推測してencryptしてoutputファイルの中身と比較するだけ。

flag = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_{}'

# Public Parameters
N = 36239973541558932215768154398027510542999295460598793991863043974317503405132258743580804101986195705838099875086956063357178601077684772324064096356684008573295186622116931603804539480260180369510754948354952843990891989516977978839158915835381010468654190434058825525303974958222956513586121683284362090515808508044283236502801777575604829177236616682941566165356433922623572630453807517714014758581695760621278985339321003215237271785789328502527807304614754314937458797885837846005142762002103727753034387997014140695908371141458803486809615038309524628617159265412467046813293232560959236865127539835290549091
e = 65537

enc=[]
ans=""
for char in flag:
    enc.append(str(pow(ord(char), e, N)) + "\n")

with open("output", mode='r') as f:
        lines=f.readlines()
        for line in lines:
            k=0
            for encnum in enc:
                if encnum == line:
                    ans = ans + flag[k]
                    break
                k=k+1

print (ans)

flag:TWCTF{padding_is_important}

2. simple_logic
codeとoutputファイルが配布。
code
Dropbox - encrypt.rb - Simplify your life
output
Dropbox - output - Simplify your life

code:
 message + key
 message XOR keyを765回繰り返す暗号化方式。
output:
 暗号化されたflagと平文と暗号文のペア6つが与えられる。どれも同じkeyで暗号化されたものと推測される。
(出なきゃ解けない)

指針:
keyは下位ビットから順番に決めていけることに気が付いたので、4bitずつ*32回でkeyを復元。
key復元の際には与えられたペアの暗号化が正しく行えるかどうかを用いた。

require 'securerandom'
require 'openssl'

ROUNDS = 765
BITS = 128
PAIRS = 6

def encrypt(msg, key)
    enc = msg
    mask = (1 << BITS) - 1
    ROUNDS.times do
        enc = (enc + key) & mask
        enc = enc ^ key
    end
    enc
end

def decrypt(msg, key)
    enc = msg
    mask = (1 << BITS) - 1
    ROUNDS.times do
        enc = enc ^ key
        enc = (enc - key) & mask
    end
    enc
end

#4bitずつ下位ビットを埋めていく再帰的運用
def DecideLowestBit(relowbitkey,lowestbit)
    #encrypt(plain_example[i])=enc_exsample[i]
    plain_example=[0x29abc13947b5373b86a1dc1d423807a,0xeeb83b72d3336a80a853bf9c61d6f254,0x7a0e5ffc7208f978b81475201fbeb3a0,
    0xc464714f5cdce458f32608f8b5e2002e,0xf944aaccf6779a65e8ba74795da3c41d,0x552682756304d662fa18e624b09b2ac5]
    enc_exsample=[0xb36b6b62a7e685bd1158744662c5d04a,0x614d86b5b6653cdc8f33368c41e99254,0x292a7ff7f12b4e21db00e593246be5a0,
    0x64f930da37d494c634fa22a609342ffe,0xaa3825e62d053fb0eb8e7e2621dabfe7,0xf2ffdf4beb933681844c70190ecf60bf]
    ans_low_key=[]

    maxloop=2 ** 4
    for loop in 1..maxloop do
        #決定した下位ビット+未決定の上位ビット
        templowbitkey=relowbitkey | (loop << (lowestbit - 4))
        mask=(1 << lowestbit) - 1
        for pair in 0..(PAIRS - 1) do
            lowplain=plain_example[pair] & mask
            lowenc=enc_exsample[pair] & mask
            if (encrypt(lowplain,templowbitkey)) & mask != lowenc then
                break
            end
        end
        if pair == (PAIRS - 1) then
            ans_low_key.push(templowbitkey)
        end
    end
    return ans_low_key
end

def CalcKey
    key_array=[0]
    for loop in 1..32 do
        temp_array=[]
        key_array.each do |lowkey|
            decide_array=DecideLowestBit(lowkey,4*loop)
            decide_array.each do |decidekey|
                temp_array.push(decidekey)
            end
        end
        key_array=temp_array
    end
    return key_array
end

key_array=CalcKey()
encrypt_flag=0x43713622de24d04b9c05395bb753d437
key_array.each do |key|
    puts "ans %x" % decrypt(encrypt_flag,key)
end

flag:TWCTF{ade4850ad48b8d21fa7dae86b842466d}


phoenixの途中の記事が気になって夜も眠れない。