[GXYCTF2019]CommonModulusAttack

[GXYCTF2019]CommonModulusAttack

题目
在这里插入图片描述
old.txt

-1029728314
1487023297
1423989849
1599108224
-1105891682
-155445570
1810855967
-86576152
-699473878
148445908
2098722170
1844125436
1326761031
552466959
-2003932646
-743304688
1450367769
1947341463
-1847355229
111050485

在这里插入图片描述
在这里插入图片描述
解题

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.txt
    public 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, cipher

def 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 = 17
    n = p * q
    phi = (p - 1) * (q - 1)
    d = inverse(e, phi)
    m = pow(c, d, n)
    return m

def mul(x):
    a = 0
    for i in bin(x)[2:]:
        a = a << 1
        if (int(i)):
            a = a ^ x
        if a >> 256:
            a = a ^ 0x10000000000000000000000000000000000000000000000000000000000000223
    return a

def dec2(m):
    while True:
        m = mul(m)
        if b"flag" in long_to_bytes(m):
            print(long_to_bytes(m))
            break

def 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}'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值