[VolgaCTF 2017 Quals] - PyCrypto 150

題目資訊

Category: Crypto + Reverse
Point: 150
Description:
This crypto algorithm uses a huge key and it’s implementation is not so trivial to reverse engineer. Isn’t it wonderful?
encrypt.py
flag.enc
pycryptography.so

解法

先看看encrypt.py:

1
2
3
4
5
6
7
8
9
10
11
#!/usr/bin/env python3
import os
from pycryptography import encrypt
from secret import flag
if __name__ == '__main__':
with open('flag.enc', 'wb+') as f:
# 160 bits security!
enc = encrypt(flag.encode(), os.urandom(20))
f.write(enc)

看到160 bits security得知key是20bytes。
再來用IDA pro看了一下pycryptography.so,嗯…放棄Orz
直接嘗試使用pycryptography的encrypt看看:

1
2
3
4
5
6
7
8
9
10
11
>>> from pycryptography import encrypt
>>> text = 'a' * 40
>>> key = 'a' * 20
>>> encrypt(text.encode(), key.encode())
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
>>> key = 'b' * 20
>>> encrypt(text.encode(), key.encode())
b'\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03'
>>> key = 'c' * 20
>>> encrypt(text.encode(), key.encode())
b'\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02'

依結果來看,encrypt()就只是在做xor而已。
直接把flag.encxortool看看:

1
2
3
4
5
$ xortool flag.enc -l 20 -c 20
1 possible key(s) of length 20:
\xd1\xffc\xf7\xc8u\xd8\xc4\x1a\x84\xca$[f\x0c\x1f\xc6\xe2\xcc\xea
Found 1 plaintexts with 95.0%+ printable characters
See files filename-key.csv, filename-char_used-perc_printable.csv

1
2
3
4
5
6
$ cat xortool_out/0.out
ol3$CTF{ @m _is_PadMa:<_Tim s_@d_Mi$$mek8
Gil'er1 Vernamewa'ean A&TeBell La's 1+gine r 2ho, in t91ci inv nt d an ad!it=3e po)ya)phabeti& s 7eam &ip-er and )at17 co-,nv nted aneau *mate! o+e-time 5adt&iphe7. ernam p7op;6ed aete)eprinte7 c=5her ,n 2hich a 5re",ousl< p7epared .eyxekepteonepaper t$pexeis c*mb,ned cha7ac r byech$racter 2it<ethe 5la,ntext m ss5"e toepr*duce th c=5hert xtk This a7e -e fu+da(entals *f <*w on -t,me pad 2or?6.
On -t,me pad ,s 5eway *f ncrypti+g 9 ssag s 2hich isedo: by ORhing eac- p8$inte=t 'yte of (es'$ge y*u 2ant to nc&<pt w,thea key b<tet#rom $ k y strea( w<,ch i6 l*ng as t-e 9 ssag i1self. f -e ke< i6 truly 7an0*m, i6 a1 least $s 8*ng a6 t-e plain1ex i is +ev r reuse! i:ewhol o7 in par1, 5+d iseke5t compl te8< sec7eti then t-e & sult,ngeciphert xtt2ill 'e ,mpossib)e * dec7yp1 or bre$k.this (ak s the o+e- ,me p$d ,nformat,ony1heor ti&ally se&ur1ewhic- m ans tha1 w1ecan )ea7n no in#or9$tioneab*ut the *ri3,nal (es6age (ap$rtt#rom ,t'6 lengthl g=3en t-e ncrypte! m16sagek E3erythin" s1 ms p rf ct righ1? 0t wh< d* we nee! a8) thi6 m*dern ci5he&6 the+? hy do w n1 d AE w-en ther i'ea "p rf ct" cip-erxefres- f7om 1917z W< re'seth catch?OOn1htimeepa! proble(s:t n th or<, this &ip< r isere$lly sec0rexebut ,n 5racticei t< re a7e #ew majo7 d&$wbac.s.eFirst, 1het.ey n ed6 to be 1ru8< ran!omk You mi"htt1hink "o what,eth17e isea 7and() Cefu:&tioneth$t giveseust7ando( n0mbers, 2e 7$n us t-at to g ne&$te o0r .ey stre$m!vk In #ac1, the r$nd|l C f0nc1ion is $ p' udor$nd*m gener$to&ewhic- o+ly give6 s1 ming)y 7andom n0mb17s, i1 w,ll loopeaf r so(e +umber o# o!1putsean! its ou1pu ecan 'e 5redicte! w<,ch m$ke6 the fu+ct=*n un7el,able fo7 s1&urit< p0rposes.eTh17e ar m*re impl me:1atio+s *f rando( f!+ctio+s mpseudor$nd;( gen ra1ors) th$t 57e us d ,n secur,tyt'ut Iewi)l not g* i:1o th$t +ow, onl< t<,ng t* r member ,s -at t7ueerandomn sst,s ve7y -ard to $ch= ve.
neesite th$t '1ateseth$t can g ne&$te t7ueerandom +um6 rs i6 RNDOM.OR, =1s ra+do(ness co(est#rom $tm*sphericeno=6e. A+ot-er prob)emt,s th$t 1he key +ee06 to 'e $s long $s -e me6sa"e itsel#, -is m$ke6 it har! t;euse #orevery lo+g 9 ssag s 'ecause ,t $kes )on" to gen ra theeke<s. I wi)l '-ow y*u $n examp)e ;# wha1 c$n go wr*ngt2hen <oueget laz< a:! useeth same k y * enc7yp1 many m ss5"es.
ak n from:eht 5s://2hi1ehatjou7ne-kword5re6s.com/2u15{u8/12jma+y-time-5ady$ttac./

可以看到解出來的文字有些是正確的,有些則像是亂碼或不可視字元,顯然解密用的key: d1 ff 63 f7 c8 75 d8 c4 1a 84 ca 24 5b 66 c 1f c6 e2 cc ea 是有些問題的。不過只要用一些已知的明文字詞來做修正就行了,譬如開頭為VolgaCTF{,還有後面的網址應該有httpswordpress

我用xortool-xorflag.enc檔案跟key做xor運算來解密,經過幾次xor測試後,最後得到修正後的key為 94 ff 63 a3 8d 75 d8 c4 1a c1 ca 24 1e 66 0c 1f c6 e2 cc ea

1
xortool-xor -f flag.enc -h 94ff63a38d75d8c41ac1ca241e660c1fc6e2ccea

解出來的plaintext:

1
2
3
4
5
VolgaCTF{N@me_is_Pad_Many_Times_P@d_Mi$$_me?}
Gilbert Vernam was an AT&T Bell Labs engineer who, in 1917, invented an additive polyalphabetic stream cipher and later co-invented an automated one-time pad cipher. Vernam proposed a teleprinter cipher in which a previously prepared key, kept on paper tape, is combined character by character with the plaintext message to produce the ciphertext. This are the fundamentals of how one-time pad works.
One-time pad is a way of encrypting messages which is done by XOR-ing each plaintext byte of message you want to encrypt with a key byte from a key stream which is long as the message itself. If the key is truly random, is at least as long as the plaintext, is never reused in whole or in part, and is kept completely secret, then the resulting ciphertext will be impossible to decrypt or break. This makes the one-time pad information-theoretically secure which means that we can learn no information about the original message (apart from it's length) given the encrypted message. Everything seems perfect right? But why do we need all this modern ciphers then? Why do we need AES when there is a "perfect" cipher, fresh from 1917? Where's the catch?
One-time pad problems: In theory, this cipher is really secure, but in practice, there are few major drawbacks. First, the key needs to be truly random. You might think: "So what, there is a rand() C function that gives us random numbers, we can use that to generate our key stream!". In fact, the rand() C function is a pseudorandom generator which only gives seemingly random numbers, it will loop after some number of outputs and its output can be predicted which makes the function unreliable for security purposes. There are more implementations of random functions (pseudorandom generators) that are used in security but I will not go into that now, only thing to remember is that true randomness is very hard to achieve. One site that states that can generate true random numbers is RANDOM.ORG, its randomness comes from atmospheric noise. Another problem is that the key needs to be as long as the message itself, this makes it hard to use for very long messages because it takes long to generate the keys. I will show you an example of what can go wrong when you get lazy and use the same key to encrypt many messages.
Taken from: https://whitehatjourney.wordpress.com/2015/08/12/many-time-pad-attack/

Flag: VolgaCTF{N@me_is_Pad_Many_Times_P@d_Mi$$_me?}