ハッカヌバトルPHDays CTFおよびCTF Qualsゞョブの解析

Positive Hack Days CTF-囜際的な情報保護競技。Capturethe Flagのゲヌム原則に埓っお開催されたす。 割り圓おられた時間にいく぀かのチヌムがネットワヌクを守り、芋知らぬ人を攻撃したす。 参加者の䞻なタスクは、敵のシステムの脆匱性を特定し、秘密情報フラグにアクセスするず同時に、システムのこのような脆匱性を怜出しお排陀するこずです。

今日のトピックでは、過去の倧䌚の参加者が盎面したいく぀かの興味深いタスクの分析を玹介したす。

歎史ず地理


今幎PHDays CTFは4回目の開催ずなりたす。 2011幎のPositive Hack Daysフォヌラムで初めおコンテストが開催され、その埌、アメリカのPPPチヌムの参加者が勝者ずなり、ロシアチヌムのリヌトモアが翌幎、オランダのEindbazenがPHDays IIIのチャンピオンになりたした。 毎幎、䞖界䞭のチヌムが、米囜から日本たで、PHDays CTFに参加しおいたす。

今幎、600以䞊のチヌムが予遞倧䌚に参加するために登録したした。

画像

ク゚ストず雰囲気


確立された䌝統によるず、ゲヌムのタスクずむンフラストラクチャは、競技の䌝説に基づいお準備されたす。これは、PHDays CTFタスクの単玔なセットを目暙のある゚キサむティングな競技に倉える特別なストヌリヌです。 たずえば、昚幎、参加者は架空のD'Errorimの䞖界を死から救いたした。 今埌の競技䌚はこの物語を続けたす。

競争のタスクは通垞、実際のプロトタむプに基づいおいたす。CTFのタスクずサヌビスの脆匱性は、実際のさたざたなシステムに芋られたす。 PHDays CTF競技は、オリゞナルのゲヌムメカニクスにずっおも興味深いものであり、ゲヌムをプレむするためのさたざたな異なる戊略の実装を可胜にしたす PHDaysのWebサむトを参照。

通垞、䞻催者は、ハッキングに盎接関係のないチヌムのために異垞なタスクを準備したす。 たずえば、PHDays 2012では、特別なゎミ箱でボヌナスフラグを芋぀けるこずで远加ポむントを獲埗でき、PHDays IIIでは、「 ハッカヌ迷路 」-レヌザヌフィヌルド、远跡センサヌ、シヌクレットドア、バグやその他の興味深いテスト。

しかし、もちろん、䞻芁なポむントは、情報セキュリティのさたざたな問題を解決する過皋でのみ獲埗されたす。 それらのいく぀かを芋おみたしょう。

解析


競争の資栌段階PHDays CTF Qualsは、タスクベヌスのCTFのタむプを指したす。぀たり、チヌムはタスクを解決し、ポむントを獲埗する必芁がありたす。 タスクは、次のカテゎリのいずれかに分類できたす。


最埌のカテゎリから始めたしょう。

明癜でないク゚スト


MPDays IV CTF Qualsの参加者は、 mp3ファむルに隠されおいるメッセヌゞを解読するために必芁なタスクの1぀ずしお。

原則ずしお、問題の状態がコンテナヌに隠されたメッセヌゞの抜出に蚀及しおいる堎合、ステガノグラフィヌの分野からの既成の゜リュヌションの1぀が䜿甚されたす。 この堎合、答えを芋぀けるには、通垞、埩号化するプログラムを遞択し、正しいキヌで実行する必芁がありたす。 ぀たり、特定のタスクを解決する際の「成功の鍵」は、著者によっお以前に芏定された適切なオプションの怜玢にありたす。

私たちの堎合、すべおが倚少異なりたす。 提案されたファむルをテキスト゚ディタで開くず、次のようになりたす。
画像
ファむルの先頭には、ID3圢匏のメタデヌタがありたす。 最初にTRCKトラック番号タグがあり、次にいく぀かのテキストがありたす。

RGB7 5.183、NULL RGB6 0.42,159 RGB5 194,244,68 RGB4 47,77,6 RGB3 44,73,141 RGB2 140,207,72 RGB1 120,156,203

この情報は、7぀のレコヌドRGB7からRGB1たでに分割できたす。

RGB7 5.183、NULL
RGB6 0.42.159
RGB5 194,244.68
RGB4 47.77.6
RGB3 44.73.141
RGB2 140,207.72
RGB1 120,156,203

各RGB識別子の埌に3぀の倀がありたす。 これらは通垞数倀ですが、ある堎合にはNULLです。 これはレコヌドの配列であり、各レコヌドには最倧3぀のシングルバむト倀が含たれるず仮定するのは簡単です。 たずえば、次のプログラムを䜿甚しお、10進コヌドを文字に゜ヌト、結合、倉換し、16進で印刷できたす。

>>> a = [120,156,203, 140,207,72, 44,73,141, 47,77,6, 194,244,68, 0,42,159, 5,183]
>>> print "".join(map(chr, a)).encode("hex")

その結果、以䞋が埗られたす。

789ccb8ccf482c498d2f4d06c2f444002a9f05b7

16進シヌケンスは、コヌド0x78 0x9Cのバむトで始たり、zlibデヌタ圧瞮アルゎリズムが䜿甚されおいるこずがわかりたす。 デフォルトのパラメヌタヌを䜿甚しお圧瞮モヌドでzlibを䜿甚する堎合、出力シヌケンスはこれらのバむトで始たりたす。

Pythonのzlibラむブラリの解凍機胜を1回呌び出すず、パックされたメッセヌゞを解凍できたす。

 >>> import zlib >>> print zlib.decompress("".join(map(chr, a))) 

そしお、テキストが衚瀺されたす

i_hate_ucucuga

倧䌚の䞻催者に送らなければならなかったのはこの旗でした。

無効な暗号化


この割り圓おは、Cryptoカテゎリに属したす。 䌝説によれば、通信セッションが傍受されたため、チヌムは送信されたメッセヌゞを解読する必芁がありたす。
画像
たず、キヌを亀換しおから暗号化されたデヌタを送信するプロセスがはっきりず芋えたす。 このような通信を構築できる暗号の基瀎に基づいお理解する必芁がありたす。

タスクはmarsず呌ばれ、これは倉曎されたRSAを意味するず想定できたす。

各キヌは2぀の郚分で構成され、䞡方の堎合の2番目の郚分は0x010001 == 65537-RSAの頻繁に䜿甚される公開指数eです。 そのため、通信セッションでは、最初に公開鍵の亀換n 1 / e 1 、n 2 / e 2 があり、次にそれらで暗号化されたメッセヌゞの亀換c1、c2がありたす。

これが本圓にRSAに䌌おいる堎合、ci = powm i 、e i 、n i 。 m 1ずm 2を芋぀ける必芁がありたす。
pow-モゞュラヌべき乗の関数、powval、exp、modulus== val exp modulus。

RSAアルゎリズムによるず


タスクn 1およびn 2の長さは1535ビットです。぀たり、因数分解単玔な因子に分解するこずはできたせん。

Pythonの拡匵ナヌクリッドアルゎリズムの実装を䜿甚したす。

 def egcd(a, b): # Extended Greatest Common Divisor if a == 0: return (b, 0, 1) else: g, y, x = egcd (b % a, a) return (g, x - (b // a) * y, y) 

数倀n 1およびn 2のGCD最倧公玄数を芋぀けたす。

 gcd = egcd(n1,n2)[0] 

GCDn 1 、n 2 の長さは1024ビットです。 数倀n 1およびn 2の他の玄数を芋぀けたす。

 p1 = n1 / gcd p2 = n2 / gcd 

p 1ずp 2は512ビットの玠数で、gcdは1024ビットの合成数おそらく512 * 512であり、分解するには倧きすぎたす...

目的のメッセヌゞm iがp iを超えない数で衚すこずができる堎合を考えたす。

n i = p i * q * rずするず、0 <m i <p iの堎合、次の匏が有効になりたす。

powm i 、e i 、n i p i == powm i 、e i 、p i 

次に、埩号化の指数d ' iは、次の匏を満たす必芁がありたす。

e i * d 'i≡1 modφp i 

d ' iの倀は、代数の補数を蚈算するこずで芋぀けるこずができたす。

d ' i = invmode i 、φp i 

プラむムp iの堎合、

φp i == p i-1 、

したがっお

d ' i = invmode i 、p i-1 

代数補数の蚈算は、Pythonの次の関数によっお実装されたす。

 def invmod(a, m): # Modular inversion g, x, y = egcd (a, m) if g == 1: return x % m raise Exception("modular inverse does not exist") 

たた、数倀を行に倉換し、最埌の文字「\ 0」から行末たでのテキストのみを残す関数が必芁になりたす。

 def showX(v): print ("%0256X" % v).decode("hex").split('\0')[-1] 

diを蚈算し、埩号化を実行したす。

 d1 = invmod(e, p1-1) d2 = invmod(e, p2-1) showX(pow(c1, d1, p1)) showX(pow(c2, d2, p2)) 

そしお結果が埗られたす

リク゚ストGET_FLAG眲名5e2d5e0323591b1c。
応答its_n0t_ab0ut_p4dd1ng

フラグは文字列「 its_n0t_ab0ut_p4dd1ng 」です。

CCC暗号割り圓お


指定ecc.pyおよびtask.pyファむルを含むsource.tar.gzアヌカむブには、楕円暗号を䜿甚しお実装されたキヌ怜蚌スキヌムが含たれたす。 アドレス195.133.87.171でポヌト5555に接続するこずにより、サヌバヌずの接続を確立できるこずが知られおいたす。

nc 195.133.87.171 5555
password: secch4l*

゜ヌスが提䟛されおいるため、分析から始める䟡倀がありたす。 実行するこずもできたす。
libnumモゞュヌルがなかったため、自分で䜜成する必芁がありたした。 前述のモゞュラヌ反転の機胜ず、それによっお䜿甚される拡匵ナヌクリッドアルゎリズムを実装するだけで十分です。

 def egcd(a, b): # Extended Greatest Common Divisor if a == 0: return (b, 0, 1) else: g, y, x = egcd (b % a, a) return (g, x - (b // a) * y, y) def invmod(a, m): # Modular inversion g, x, y = egcd (a % m, m) if g != 1: raise Exception("modular inverse does not exist") else: return x % m 

したがっお、 task.pyのmain関数

 def main(): print "Auth:“ auth = raw_input() if hashlib.sha1(auth).hexdigest() != "375d5c01ca1b8c3863024d10aac7713472eb5033": # secch4l* print "nope“ return prefix = os.urandom(8) print "Proof of work, please“ print "Prefix is (hexed) ", prefix.encode("hex") test = raw_input().decode("hex") if not test.startswith(prefix) or len(test) > 16: print "nope“ return h = hashlib.sha1(test).hexdigest() if not h.startswith("000000"): print "nope“ return goflag() 

行が読み取られたす。SHA-1は、指定された倀 "secch4l *"ず等しくなければなりたせん。
次に、ランダムな8バむトのプレフィックスがクラむアントに送信されたす。 バむトは16進文字列ずしお゚ンコヌドされたす。 応答ずしお、クラむアントは指定されたプレフィックスで始たるように16バむト以䞋の文字列を送信する必芁があり、この文字列のSHA-1倀の最初の3バむトはれロでなければなりたせん。 すべおのステップが成功するず、goflag関数が呌び出されたす。

次のコヌドは、サヌバヌに接続し、パスワヌドを送信し、プレフィックスを受信し、応答を蚈算しお送信したす。

 def readLn(sock): a = [] while True: c = sock.recv(1) if '\n' == c: return "".join(a) a.append(c) HOST = "195.133.87.171" PORT = 5555 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((HOST, PORT)) print readLn(sock) # Auth: sock.send("secch4l*\n") print readLn(sock) # Proof of work, please s = readLn(sock) print s # Prefix is (hexed) 0b3997e62b9ffbf4 prefix = s.split()[-1].decode("hex") for i in xrange(0x7FFFFFFF): s = "%s%X" % (prefix, i) if hashlib.sha1(s).digest()[:3] == '\0\0\0': break sock.send(s + '\n') 

クラむアント偎でこのコヌドを実行した埌、サヌバヌはgoflag関数を実行し、次のテキストを衚瀺したす。

ECパスワヌドチェック
R = 572115218124168948525078362547166172445820217705568707355669424304224832114
共有秘密= R ^パスワヌド
暗号化されたメッセヌゞ7a93846a011e0d0382e94f32d705239e6298169dcec20da5d6

goflag関数で䜕が起こるか

 def goflag(): print "EC PASSWORD CHECK" r = random.randint(31337, 1 << 250) R = p256.power(G, r) print "R =", R print "SHARED SECRET = R ^ PASSWORD" S = p256.power(R, PASSWORD) key = p256.derive(S) cipher = encrypt(FLAG, key) print "ENCRYPTED MESSAGE:", cipher.encode("hex") 

楕円曲線の非察称暗号化が䜿甚されたす。 NISTが掚奚するP-256曲線が遞択されおいたす。 カヌブポむントに察する操䜜の実装には、明らかな脆匱性は含たれおいたせん。

Rの倀は知っおいたすが、PASSWORDpassword.txtファむルからサヌバヌによっお読み取られるの倀がわからないず、Sを蚈算できたせん。Sを知っおいるず、キヌを簡単に蚈算できたす。 暗号化ぱラヌで実装されおいるのでしょうか

task.pyのencrypt機胜

 def encrypt(msg, key): iv = os.urandom(8) stream = hashlib.sha256(iv + key).digest() stream = hashlib.sha256(stream + iv + key).digest() cipher = iv + xor(msg, stream) return cipher 

このコヌドは、暗号化されたメッセヌゞの前にランダムな8バむトの初期化ベクトルivがあり、2぀のSHA-256蚈算の出力ずしおガンマが生成されたXORフラグずしお暗号化が実行されるこずを瀺したす。 キヌの意味を知らなくおも、ガンマを取埗するのは非珟実的です。 しかし、プログラムでキヌはどのように取埗されたすか

task.pyの掟生関数

 def derive(self, p): return hashlib.sha256(str((p[0] << 10) / p[1])).digest() 

ポむントSの倀xずyの2぀の座暙で構成されるが入力SHA-256ずしお䜿甚されるこずがわかりたす。 実際、strintx * 1024 / yがハッシュ入力に提䟛されたす。 xずyは倀が近いこれらは倧きな敎数であるため、算術挔算の結果は1024に近いはずですただし、数回それを超えるこずがありたす。

したがっお、掟生関数の特定の実装により、キヌ倀は非垞に少数の状態をずるこずができたす。 それらすべおを単玔に゜ヌトし、各キヌのメッセヌゞを埩号化しおみおください。印刷された文字のみで構成されおいる堎合、成功しおいたす。

 import hashlib, ecc enc = "7a93846a011e0d0382e94f32d705239e6298169dcec20da5d6".decode("hex") iv = enc[:8] def decrypt(key): stream = hashlib.sha256(iv + key).digest() stream = hashlib.sha256(stream + iv + key).digest() return ecc.xor(enc[8:], stream) for i in xrange(0x7FFFFFFF): s = decrypt(hashlib.sha256(str(i)).digest()) for c in bytearray(s): if c < 32 or c >= 128: break else: print s # ecc_is_too_s3cure break 

したがっお、フラグは「ecc_is_too_s3cure」ずいう行です。

リバヌス゚ンゞニアリング。 Shadelt900


リバヌス゚ンゞニアリングは、別の䞀般的なゞョブカテゎリです。 CTFに加えお、Best ReverserコンテストはPHDaysコンテストプログラムに含たれおいたす。

Shadelt900の割り圓おは、前の3぀ず同様に、2014幎1月に開催されたPHDays IV CTF Qualsプログラムの䞀郚でした。 チヌムは「derrorim_enc.bmp」ずいう画像を埩号化する必芁がありたした。 暗号化に䜿甚したツヌルはShadelt9000.exeず呌ばれおいたしたが、埩号化ツヌルが芋぀かりたせんでした。 これが画像です

画像

Shadelt9000.exeファむルをよく芋るず、アプリケヌションがOpenGLを䜿甚しおいるこずが明らかになりたす。 著䜜暩むンフレヌト1.2.8 Copyright 1995-2013 Mark Adlerもあり、このプログラムが䞀般的なzlib圧瞮ラむブラリを䜿甚しおいるこずを瀺しおいたす。

zlib関数の呌び出し元の逆アセンブラを芋るず、そのようなコヌドがすぐに芋぀かりたす。

画像

アドレス0x47F660および0x47F7B8には、zlibによっおパックされたデヌタ配列がありたす。 それらを開梱したす。

 from zlib import decompress as unZ base = 0x47C000 - 0x7AE00 # data section base ab=open("ShadeIt9000.exe", "rb").read() open("1.txt", "w").write(unZ(ab[0x47F660-base:],-15)) open("2.txt", "w").write(unZ(ab[0x47F7B8-base:],-15)) 

解凍埌、1.txtファむルにはピクセルシェヌダヌが含たれおいたす。

 #version 330 uniform sampler2D u_texture; uniform sampler2D u_gamma; varying vec4 texCoord0; varying vec3 v_param; uint func(vec3 co){ return uint(fract(sin(dot(co ,vec3(17.1684, 94.3498, 124.9547))) * 68431.4621) * 255.); } uvec3 rol(uvec3 value, int shift) { return (value << shift) | (value >> (8 - shift)); } const uvec3 m = uvec3(0xff); void main() { uvec3 t = uvec3(texture2D(u_texture, vec2(texCoord0)).rgb * 0xff) & m; uvec3 g = uvec3(texture2D(u_gamma, vec2(texCoord0)).rgb * 0xff) & m; int s = int(mod(func(v_param), 8)); t = rol(t, s); vec3 c = vec3((t ^ g) & m) / 0xff; gl_FragColor = vec4(c, 1.); } 


2.txtファむルには頂点シェヌダヌが含たれおいたす。

 attribute vec3 a_param; varying vec4 texCoord0; varying vec3 v_param; void main(void) { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; texCoord0 = gl_MultiTexCoord0; v_param = a_param; } 

ピクセルシェヌダヌに関する䞻な情報は赀で匷調衚瀺されおいたす。

画像

倉数tは、凊理されたテクスチャ入力ファむルの珟圚の芁玠であるこずがわかりたす。
倉数gには、珟圚のガンマ芁玠擬䌌ランダムな方法で生成された。
倉数sには、埌でsの埪環シフトに䜿甚される倀がありたす。
出力倀は実際には次のように蚈算されたす

(rol(t,s) ^ g)

さらに、同じ入力ファむルでプログラムを耇数回実行するず、各芁玠のgの倀は開始から開始たで倉化し、tずsは同じたたです。

ガンマの生成方法を確認したす。

 unsigned char *pbGamma = malloc(cbGamma); srand(time(0)); for (i = 0; i < cbGamma; i++) { pbGamma[i] = rand(); } 

珟圚の時刻に䟝存しおいるこずがわかりたす。

元のアヌカむブから、derrorim_enc.bmpファむルが2014幎1月21日18時37分52秒に䜜成されたこずがわかりたす。
その時点でtime関数が返す倀を取埗したす。

 >>> import time >>> print hex(int(time.mktime((2014,1,21, 18,37,52, 0,0,0)))) 


0x52de8640

次に、ShadeIt9000.exeファむルをShadeIt9000_f.exeにコピヌしお修正したす。

オフセット00015557でバむトが必芁

E8 A5 31 01 00

に眮き換える

B8 40 86 DE 52

これは、眮換ず同等です

mov eax,52de8640hたす。

したがっお、ShadeIt9000_fのバヌゞョンを取埗したした。これは、察象のファむルが暗号化されたずきず同じ色域で垞に暗号化されたす。
次に、画像の解読に圹立぀倀を準備する必芁がありたす。

 import os bmp=open("derrorim_enc.bmp", "rb").read() hdr = bmp[:0x36] abData = bytearray(bmp[0x36:]) cbBody = len(bmp) - len(hdr) open("00.bmp", "wb").write(hdr + '\0'*cbBody) open("XX.bmp", "wb").write(hdr + '\2'*cbBody) os.system("ShadeIt9000_f.exe 00.bmp") os.system("ShadeIt9000_f.exe XX.bmp") 

00_enc.bmpファむルには、れロバむトで構成される画像の暗号化の結果が含たれたす。 これは、最も玔粋な圢匏のガンマになりたす。

XX_enc.bmpファむルには、倀2のバむトで構成される画像の暗号化結果が含たれたす。これにより、各バむトが埪環的にシフトしたビット数がわかりたす。

最埌に、Shadelt9000を埩号化したす。

 def rol(v,i): return (((v<<i) & 0xFF) | ((v>>(8-i)) & 0xFF)) def ror(v,i): return (((v>>i) & 0xFF) | ((v<<(8-i)) & 0xFF)) dRot = {rol(1,i):i for i in xrange(8)} bmp=open("derrorim_enc.bmp", "rb").read() hdr = bmp[:0x36] abData = bytearray(bmp[0x36:]) abGamma = bytearray(open("00_enc.bmp", "rb").read()[0x36:]) abRot = bytearray(open("XX_enc.bmp", "rb").read()[0x36:]) for i,b in enumerate(abGamma): abRot[i] = dRot[abRot[i] ^ b] for i,b in enumerate(abGamma): abData[i] = ror(abData[i] ^ b, abRot[i]) open("derrorim.bmp", "wb").write(hdr + str(abData)) 

私達は埗る

画像

タスクを解決するための正しい方法ですが、最も効果的ではありたせん。 もっず短い方法がありたす。

アドレス0x47F848および0x47F9A0の頂点シェヌダヌのすぐ埌ろに、ピクセルず頂点シェヌダヌのパックされたzlibコヌドがあり、逆倉換を実行したす。 おそらく、圌は誀っおタスクデザむナヌに忘れられおいたのでしょう。 たたは、意図的に残しおおくこずもできたす。

暗号化ず埩号化の頂点シェヌダヌコヌドは同䞀であるため、それらに觊れおも意味がありたせん。 ピクセルシェヌダヌを亀換するずどうなりたすか

ShadeIt9000_f.exeをShadeIt9000_d.exeにコピヌしお修正したす。

00015775: 60 F6 ==> 48 F8

次に、ShadeIt9000_d.exe derrorim_enc.bmpを実行したす。 そしお、埩号化されたファむルderrorim_enc_enc.bmpの出力を取埗したす。これは小さなアヌティファクトを陀きPythonスクリプトで埩号化されたものず䞀臎したす。

今日は以䞊です ご枅聎ありがずうございたした。コメントの質問にお答えしたす。

PHDays IV CTFのファむナルは5月21日ず22日にPositive Hack Daysフォヌラムで開催されたす。 競技の進行状況をサむト䞊で盎接監芖できるだけでなく、モバむルアプリケヌションを䜿甚しお監芖するこずもできたす。 ニュヌスに埓っおください

たた読む


PHDays IVのオンラむンコンテストHashRunnerず「 Competitive Intelligence 」ぞの参加が既に登録されおいるこずをお知らせしたす。

PSすべおのPHDays CTFおよびCTF Quals割り圓おのアヌカむブは、PHDays Webサむトで芋぀けるこずができたす。 だから、あなたが自分自身をテストしたいのであれば、先に進んでください

PPSこのトピックで瀺されおいるタスクの詳现な分析は、Dmitry Sklyarovが䞻催する特別なりェビナヌで行われたした。 りェビナヌ゚ントリは、 http  //my.webinar.ru/record/290241/で入手できたす。

Source: https://habr.com/ru/post/J221991/


All Articles