[GXYCTF2019]CommonModulusAttack
生活随笔
收集整理的這篇文章主要介紹了
[GXYCTF2019]CommonModulusAttack
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
[GXYCTF2019]CommonModulusAttack
題目
old.txt
解題
class文件是需要反翻譯的,在線反翻譯網址:http://javare.cn/
反翻譯完之后得到:
import java.io.IOException; import java.io.PrintWriter; import java.math.BigInteger; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Random; import java.util.Scanner; import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec;public class CommonModulusAttack {private Random random = new Random();private ArrayList states = new ArrayList(24);private String seed;private int statespoint = 0;private int stateselse = 24;public void oldtest() {try {PrintWriter var1 = new PrintWriter("old.txt", "UTF-8");for(int var2 = 0; var2 < 20; ++var2) {int var3 = this.random.nextInt();var1.println(var3);}var1.close();} catch (IOException var4) {var4.printStackTrace();}}public BigInteger generate_init_state() {BigInteger var1 = BigInteger.valueOf(0L);char[] var2 = this.seed.toCharArray();char[] var3 = var2;int var4 = var2.length;for(int var5 = 0; var5 < var4; ++var5) {char var6 = var3[var5];var1 = var1.shiftLeft(1);if(var6 == 49) {var1 = var1.xor(new BigInteger(this.seed, 2));}if(var1.shiftRight(256) != BigInteger.ZERO) {var1 = var1.xor(new BigInteger("10000000000000000000000000000000000000000000000000000000000000223", 16));}}return var1;}public void gen_states() {BigInteger var1 = this.generate_init_state();BigInteger var2 = BigInteger.valueOf(17L);ArrayList var3 = new ArrayList(24);ArrayList var4 = new ArrayList(24);for(int var5 = 0; var5 < 24; ++var5) {BigInteger var6 = BigInteger.probablePrime(512, this.random);BigInteger var7 = BigInteger.probablePrime(512, this.random);BigInteger var8 = var6.multiply(var7);BigInteger var9 = var1.modPow(var2, var8);var3.add(var8);var4.add(var9);}try {PrintWriter var11 = new PrintWriter("product", "UTF-8");for(int var12 = 0; var12 < 24; ++var12) {var11.println(((BigInteger)var3.get(var12)).toString());this.states.add(var4.get(var12));}var11.close();} catch (IOException var10) {var10.printStackTrace();}}public byte[] encrypt(BigInteger var1) {try {IvParameterSpec var2 = new IvParameterSpec(new byte[16]);byte[] var3 = new byte[16];this.random.nextBytes(var3);SecretKeySpec var4 = new SecretKeySpec(var3, "AES");Cipher var5 = Cipher.getInstance("AES/CBC/NoPadding");var5.init(1, var4, var2);byte[] var6 = new byte[128];byte[] var7 = var1.toByteArray();int var8;if(var7.length == 129) {for(var8 = 0; var8 < 128; ++var8) {var6[var8] = var7[var8 + 1];}} else {for(var8 = 0; var8 < 128; ++var8) {var6[var8] = var7[var8];}}byte[] var10 = var5.doFinal(var6);return var10;} catch (Exception var9) {var9.printStackTrace();return null;}}public void gen_new_states() {for(int var1 = 0; var1 < 24; ++var1) {BigInteger var2 = (BigInteger)this.states.get(this.statespoint - 24 + var1);byte[] var3 = this.encrypt(var2);this.states.add(new BigInteger(var3));}this.stateselse += 24;}public byte[] stateconvert(BigInteger var1) {byte[] var2 = this.encrypt(var1);return var2;}public byte[] lrandout() {if(this.stateselse > 0) {--this.stateselse;BigInteger var1 = (BigInteger)this.states.get(this.statespoint);++this.statespoint;return this.stateconvert(var1);} else {this.gen_new_states();return this.lrandout();}}public static String byte2hex(byte[] var0) {StringBuffer var1 = new StringBuffer(var0.length * 2);for(int var2 = 0; var2 < var0.length; ++var2) {if((var0[var2] & 255) < 16) {var1.append("0");}var1.append(Long.toString((long)(var0[var2] & 255), 16));}return var1.toString();}public static String convert_2_binary(String var0) {byte[] var1 = var0.getBytes();StringBuilder var2 = new StringBuilder();byte[] var3 = var1;int var4 = var1.length;for(int var5 = 0; var5 < var4; ++var5) {byte var6 = var3[var5];int var7 = var6;for(int var8 = 0; var8 < 8; ++var8) {var2.append((var7 & 128) == 0?0:1);var7 <<= 1;}}return var2.toString();}public void initseed() {try {Scanner var1 = new Scanner(Paths.get("flag", new String[0]), "UTF-8");String var2 = var1.next();String var3 = convert_2_binary(var2);this.seed = var3;} catch (IOException var4) {var4.printStackTrace();}}public static void main(String[] var0) {CommonModulusAttack var1 = new CommonModulusAttack();var1.oldtest();var1.initseed();var1.gen_states();for(int var2 = 0; var2 < 24; ++var2) {var1.lrandout();}try {PrintWriter var5 = new PrintWriter("new.txt", "UTF-8");for(int var3 = 0; var3 < 24; ++var3) {var5.println(byte2hex(var1.lrandout()));}var5.close();} catch (IOException var4) {var4.printStackTrace();}System.out.println("Bye!");} }感覺自己Java還是太菜了,代碼一長就發怵
先是進行了20次的.random.nextInt(),得到old.txt
然后initseed把flag進行一系列運算,進一步分析得知是在GF(2256)中將flag平方了一下;
state通過RSA part生成的24組(p,q),e=17,加密得到this.states (len(states == 24))
lrandout先AES/CBC完整加密了一次this.states的24個值,但該次并未更新this.states
由于this.stateselse此時為0,因此執行lrandout會先新生成24個state(即調用gen_new_states)
在舊states后新增一長度為24的states后,用新增的states加密得到的結果即為new.txt中內容
啊,智商不夠啊😭
來看某大佬的代碼
SeedAttack.java
public class SeedAttack {private long a = 0x5deece66dL;private long b = 11L;private long m = 0xffffffffffffL;public long crack_seed(long d1, long d2) throws Exception {for (int i = 0; i <= 0xffff; i++) {long seed = (d1 << 16) + i;long guess_d2 = (a * seed + b & m) >>> 16;if (guess_d2 == d2) {System.out.println("[+] PRNG's seed: " + String.valueOf(seed));return seed;}}throw new Exception("[!] PRNG crack failed!");}// public static void main(String[] args) { // SeedAttack localSeedAttack = new SeedAttack(); // long d1 = -1029728314L; // long d2 = 1487023297L; // try { // long seed = localSeedAttack.crack_seed(d1, d2); // System.out.println(seed); // } catch (Exception e) { // System.out.println(e.getMessage()); // } // } }CMA.java
import java.util.Random; import java.io.PrintWriter; import java.io.IOException; import java.util.ArrayList; import java.math.BigInteger;public class CMA {private Random random = new Random();public CMA() {long PRNG_seed = 0L;SeedAttack localSeedAttack = new SeedAttack();long d1 = -1029728314L;long d2 = 1487023297L;try {PRNG_seed = localSeedAttack.crack_seed(d1, d2); // System.out.println(PRNG_seed);} catch (Exception e) {System.out.println(e.getMessage());}this.random.setSeed(PRNG_seed ^ 0x5DEECE66DL);}// discard trash which generate old.txtpublic void discardTrash() {for (int i = 0; i < 19; i++) {int j = this.random.nextInt();}}public void genRSA() {BigInteger e = BigInteger.valueOf(17L);ArrayList<ArrayList> RSA_params = new ArrayList<ArrayList>(24);for (int i = 0; i < 24; i++) {ArrayList curRSAparams = new ArrayList(2);BigInteger p = BigInteger.probablePrime(512, this.random);BigInteger q = BigInteger.probablePrime(512, this.random);curRSAparams.add(p);curRSAparams.add(q);RSA_params.add(curRSAparams);}try {PrintWriter localPrintWriter = new PrintWriter("prikey", "UTF-8");for (int i = 0; i < 24; i++) {ArrayList curRSAparams = RSA_params.get(i);String p = curRSAparams.get(0).toString();String q = curRSAparams.get(1).toString();localPrintWriter.println("(" + p + ", " + q + ")");}System.out.println("[+] RSA's priKey found");localPrintWriter.close();} catch (IOException error) {error.printStackTrace();}}public static String byte2hex(byte[] paramArrayOfByte){StringBuffer localStringBuffer = new StringBuffer(paramArrayOfByte.length * 2);for (int i = 0; i < paramArrayOfByte.length; i++){if ((paramArrayOfByte[i] & 0xFF) < 16) localStringBuffer.append("0");localStringBuffer.append(Long.toString(paramArrayOfByte[i] & 0xFF, 16));}return localStringBuffer.toString();}public void genKey() {try {PrintWriter localPrintWriter = new PrintWriter("AESkey", "UTF-8");for (int i = 0; i < 72; i++) {byte[] key = new byte[16];this.random.nextBytes(key);localPrintWriter.println(byte2hex(key));}System.out.println("[+] AES's key found");localPrintWriter.close();} catch (IOException e) {e.printStackTrace();}}public static void main(String[] args) {CMA exp = new CMA();exp.discardTrash();exp.genRSA();exp.genKey();} }exp.py
import re from Crypto.Cipher import AES from binascii import unhexlify from Crypto.Util.number import *def getData():pqs = []with open('prikey', 'r') as fRSA:for line in fRSA:pq = re.findall(r"\((.*), (.*)\)", line)[0]pqs.append((int(pq[0]), int(pq[1])))with open('AESkey', 'r') as fAES:key = [unhexlify(line.strip()) for line in fAES]key = [key[:24], key[24:48], key[48:]]with open('new.txt', 'r') as fCIPHER:cipher = [unhexlify(line.strip()) for line in fCIPHER]return pqs, key, cipherdef dec1(p, q, c, key1, key2):aes2 = AES.new(key2, AES.MODE_CBC, iv=b"\x00"*16)c = aes2.decrypt(c)aes1 = AES.new(key1, AES.MODE_CBC, iv=b"\x00"*16)c = bytes_to_long(aes1.decrypt(c))e = 17n = p * qphi = (p - 1) * (q - 1)d = inverse(e, phi)m = pow(c, d, n)return mdef mul(x):a = 0for i in bin(x)[2:]:a = a << 1if (int(i)):a = a ^ xif a >> 256:a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223return adef dec2(m):while True:m = mul(m)if b"flag" in long_to_bytes(m):print(long_to_bytes(m))breakdef main():pqs, key, cipher = getData()m = dec1(pqs[0][0], pqs[0][1], cipher[0], key[1][0], key[2][0])dec2(m)if __name__ == '__main__':main()# b'flag{86824087489918371343860652}'總結
以上是生活随笔為你收集整理的[GXYCTF2019]CommonModulusAttack的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [NPUCTF2020]Mersenne
- 下一篇: [羊城杯 2020]GMC