CTF中RSA題型解題思路及技巧
0x01 RSA演算法簡介
為了方便小白咀嚼後文,這裡先對RSA金鑰體制做個簡略介紹(簡略因為這不是本文討論的重點)
- 選擇兩個大素數p和q,計算出模數N = p * q
- 計算φ = (p−1) * (q−1) 即N的尤拉函式,然後選擇一個e (1<e<φ),且e和φ互質
- 取e的模反數為d,計算方法: e * d ≡ 1 (mod φ)
- 對明文m進行加密:c = pow(m, e, N),得到的c即為密文
- 對密文c進行解密,m = pow(c, d, N),得到的m即為明文
整理一下得到我們需要認識和記住的引數
- p 和 q :大整數N的兩個因子(factor)
- N:大整數N,我們稱之為模數(modulus
- e 和 d:互為模反數的兩個指數(exponent)
- c 和 m:分別是密文和明文,這裡一般指的是一個十進位制的數
然後我們一般稱
- (N,e):公鑰
- (N,d):私鑰
0x02 CTF中的RSA題型
CTF中的RSA題目一般是將flag進行加密,然後把密文(即c)和其他一些你解題需要的資訊一起給你,你需要克服重重難關,去解密密文c,得到flag(即m),一般有下列題型
公鑰加密文
這是CTF中最常見最基礎的題型,出題人會給你一個公鑰檔案(通常是以.pem或.pub結尾的檔案)和密文(通常叫做flag.enc之類的),你需要分析公鑰,提取出(N,e),通過各種攻擊手段恢復私鑰,然後去解密密文得到flag。
文字文件
對於第一種題型,耿直點的出題人直接給你一個txt文字文件,裡面直接寫出了(N,e,c)所對應的十進位制數值,然後你直接拿去用就行了。當然也不都是給出(N,e,c)的值,有時還會給出其他一些引數,這時就需要思考,這題具體考察的什麼攻擊方法
pcap檔案
有時出題人會給你一個流量包,你需要用wireshark等工具分析,然後根據流量包的通訊資訊,分析題目考察的攻擊方法,你可以提取出所有你解題需要用到的引數,然後進行解密
本地指令碼分析
題目會給你一個指令碼和一段密文,一般為python編寫,你需要逆向檔案流程,分析指令碼的加密過程,寫出對應的解密指令碼進行解密
遠端指令碼利用
這種題型一般難度較大。題目會給你一個執行在遠端伺服器上的python指令碼和伺服器地址,你需要分析指令碼存在的漏洞,確定攻擊演算法,然後編寫指令碼與伺服器互動,得到flag
0x03 RSA的常見攻擊方法
看不懂的彆著急,直接跳過看後面的小白福利環節
當模數N過小時
RSA的非對稱體制是建立在大整數分解難題上的,所以最基本的攻擊方法就是當模數N過小時,我們可以寫個指令碼直接爆破他的因子,如
那麼靠爆破來分解大整數N,我們可以分解多大的呢?
2009年12月12日,編號為 RSA-768 (768bits,232 digits)數也被成功分解。—-百度百科
然而現在一般RSA在實際應用裡都是2048位的,在CTF中出現的也不會太小,一般是不可能讓你爆破分解的,都是要用到一些攻擊演算法的,下面我來介紹下這些演算法
分解大整數的一些演算法
如果說N小了容易被分解,那麼N越大就越安全嗎?不然,RSA金鑰的安全不只和模數N有關,與它的指數:e和d也息息相關
這裡假設我們從題目獲得了公鑰(N,e)和待解密的密文c,由RSA的加解密過程,我們知道,如果要解密密文,我們要得到e的模反數d,而d是要我們去求解的。
這裡討論我們如何知道什麼時候該用什麼演算法,不進行數學證明及原理分析。下面我例舉其中幾個比較常見且容易理解的,因為作為最後的小白福利,我已經把這些演算法都整合進去了,感興趣的可以檢視原始碼
Wiener’s attack
https://en.wikipedia.org/wiki/Wiener%27s_attack
當 d < (1/3) N^(1/4)時,我們可以通過Wiener’s attack分解得到d
費馬分解
當大整數N的兩個因子p和q相近時,我們可以通過費馬分解的辦法很快分解大整數
Small q
當q較小時,即|p-q|較大時,我們可以直接爆破因子
Boneh Durfee Method
當d滿足 d ≤ N^0.292 時,我們可以利用該方法分解N,理論上比wiener attack要強一些。
yafu
yafu使用最強大的現代演算法去自動化的分解輸入的整數。大多數的演算法都實現了多執行緒,讓yafu能充分利用多核處理器(演算法包括 SNFS, GNFS, SIQS, 和 ECM)。
factordb
如果對一個大整數用一些特殊演算法也分解不了的時候,我們可以在 http://factordb.com/ 中查詢一下資料庫,說不定就能找到其因子
其他一些題型
有些題會給你一些隨機生成的大整數,一般來說是無法直接分解的,不過一般會給我們其他切入點
Rabin演算法
當e等於2時
小公鑰指數攻擊
當e十分小時,比如e等於3時
d洩露攻擊
如果我們知道一組過期的(N,e1,d1)和一組由新的e2組成的公鑰及其加密的密文(N,e2,c),我們可以由(e1,d1)得到模數N的兩個因子p和q,再去算e2的模反數d2,去解密密文
共模攻擊
使用相同的模數 N 、不同的私鑰,加密同一明文訊息
模不互素
兩個公鑰的N不互素時
Known High Bits Factor Attack
我們知道模數N其中一個因子的高位元位時
Stereotyped messages
如果你知道明文中最重要的部分,您可以使用此方法找到訊息的其餘部分。
Basic Broadcast Attack
同一個加密指數e和不同且互素的模數N加密了同一個密文,併發送給了其他e個使用者
0x04 小白福利環節
上面有一堆讓人頭大的演算法,比如分解一個大整數可能就有十來種演算法,當然不是每個演算法都能成功分解我們題目給的大整數的,如果我們挨個嘗試,不僅浪費精力還浪費時間,等你找到正確的演算法,已經與一血,二血,三血無緣了。所以我們需要一個自動化的工具,來幫助我們嘗試可能的演算法,並恢復出私鑰或者解密密文。於是我就用幾天時間寫了這麼一款小工具。
專案地址
https://github.com/D001UM3/CTF-RSA-tool
環境依賴
安裝libnum
安裝gmpy2
參考原文:https://www.cnblogs.com/pcat/p/5746821.html
原文裡面有的版本過老,會安裝失敗,可以參考我的安裝過程:https://d001um3.github.io/2018/01/24/CTF-RSA-tool-install/
克隆倉庫,安裝依賴
安裝sagemath(可選)
安裝sagemath的以支援更多的演算法,提高解題成功率,嫌麻煩也可以不安裝
官網:http://www.sagemath.org
我的安裝過程:https://d001um3.github.io/2017/12/06/sage/
幾個解題例子(更多參考專案目錄下example.txt)
在大多數情況下,你只需要把題目給的資訊輸入給指令碼,指令碼就會自動完成剩下的工作如:
1:題目給了一個公鑰檔案和密文,直接用 --key
或 -k
指定公鑰,用 —decrypt 指定密文檔案就行了
2:題目給了你如(N,e,c)的十進位制值,分別通過-N
,-e
,-c
輸入就行了
3:上面那種情況,如果題目是把這些引數都寫入一個文字檔案,如txt中,直接用 --input
或 -i
指定文字檔案就行了
具體的例子:
Wiener’s attack
python solve.py --verbose --private -i examples/wiener_attack.txt
或者通過命令列,只要指定對應引數就行了
python solve.py --verbose --private -N 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597 -e 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619
利用 factordb.com 分解大整數
python solve.py --verbose -k examples/jarvis_oj_mediumRSA/pubkey.pem --decrypt examples/jarvis_oj_mediumRSA/flag.enc
small q attack
python solve.py --verbose --private -k examples/small_q.pub
費馬分解(p&q相近時)
python solve.py --verbose --private -i examples/closed_p_q.txt
Common factor between ciphertext and modulus attack(密文與模數不互素)
python solve.py --verbose -k examples/common_factor.pub --decrypt examples/common_factor.cipher --private
small e
python solve.py --verbose -k examples/small_exponent.pub --decrypt examples/small_exponent.cipher
Rabin 演算法 (e == 2)
python solve.py --verbose -k examples/jarvis_oj_hardRSA/pubkey.pem --decrypt examples/jarvis_oj_hardRSA/flag.enc
Small fractions method when p/q is close to a small fraction
python solve.py --verbose -k examples/smallfraction.pub --private
Known High Bits Factor Attack
python solve.py --verbose --private -i examples/KnownHighBitsFactorAttack.txt
d洩漏攻擊
python solve.py --verbose --private -i examples/d_leak.txt
模不互素
python solve.py --verbose --private -i examples/share_factor.txt
共模攻擊
python solve.py --verbose --private -i examples/share_N.txt
Basic Broadcast Attack
python solve.py --verbose --private -i examples/Basic_Broadcast_Attack.txt
再列舉幾個實用的小功能
輸入N與e建立公鑰
python solve.py -g --createpub -N your_modulus -e your_public_exponent -o public.pem
檢視金鑰檔案
python solve.py -g --dumpkey --key examples/smallfraction.pub
將加密檔案轉為十進位制(方便寫入文字,配合-i
需要)
python solve.py -g --enc2dec examples/jarvis_oj_hardRSA/flag.enc
下面來介紹下我寫這個工具的思路
這個工具如何工作
根據題目給的引數型別,自動判斷應該採用哪種攻擊方法,並嘗試得到私鑰或者明文,從而幫助CTFer快速拿到flag或解決其中的RSA考點
大體思路
判斷輸入
首先,識別使用者的輸入,可以是證書 pem 檔案,也可以通過命令列引數指定n
,e
等變數的值,甚至可以通過命令列指定題目所給的txt檔案並自動識別裡面的變數
判斷攻擊演算法
根據取到的引數型別及數量,選取可能成功的方法並採用一定的優先順序逐個嘗試。
如大整數分解的題型:給了一個公鑰和一個加密的密文,我們需要先分解大整數N,然後得到私鑰再去解密。考點在於大整數分解,指令碼的關鍵程式碼在CTF-RSA-tool/lib/factor_N.py中的solve函式
選擇輸出
CTFer可以通過命令列選擇是輸出私鑰還是輸出解密後的密文,還是一起輸出,不過非 --input
(文字文件自動識別攻擊) 的情況下,請至少選擇 --private
(列印得到的私鑰) 或 --decrypt
(解密一個加密的檔案) 或 --decrypt_int
(解密一個十進位制數) 中的一個。
0x05.還是沒有得到flag
首先如果題型是大整數分解的話,你還可以嘗試使用其他工具如 yafu 來分解,如果還是不能分解,你就得再好好看看這題是不是另有切入點了。
其次,如果是一些你沒見過的題型的話,建議通過百度,谷歌,github搜一下,一般還是能搜到的類似的題目甚至原題的
最後,如果還是做不出來,先女裝一下再去做題,聽大佬們說有buff加成
0x06.寫在最後
1:大部分演算法都是參照網上,我只是做了下整合彙總,並儘量使其易懂易用,程式碼不精,大佬輕噴。 2:還有很多實用的演算法(有關 Coppersmith 的演算法和一些分解大整數的演算法)暫時沒有加進去,一是精力有限,二是能力有限,三是沒遇到相關題型,以後會不斷完善。 3:大佬們覺得好用的話,點個 star 收藏一下,也歡迎各位來 contribute 和提 issues