Category - SquareCTF2018

看到好多人都是用ocr做的,但是准确度好差啊。。
我是解析字体文件做的。
首先找到每个真字符与显示的图片对应的表。
title

然后根据图片尺寸找到对应显示的字符,再替换。
(如果尺寸都一样的话,匹配下面的像素点也行)
title

  1. import requests
  2. import base64
  3. import io
  4. import re
  5. from fontTools.ttLib import TTFont
  6. url = 'https://hidden-island-93990.squarectf.com/ea6c95c6d0ff24545cad'
  7. sess = requests.Session()
  8. font_ptn = re.compile(r"(?<=data:application/font-ttf;charset=utf-8;base64,)[^']*")
  9. cipher_ptn = re.compile(r'(?<=<h1>Captcha</h1><p>)[^<]*')
  10. token_ptn = re.compile(r'(?<=<input type="hidden" name="token" value=")\d+')
  11. sizes = {
  12. '0': (0, 0, 585, 660),
  13. '1': (0, 0, 311, 673),
  14. '2': (0, 0, 497, 704),
  15. '3': (0, 0, 548, 684),
  16. '4': (0, -3, 576, 690),
  17. '5': (0, 0, 531, 690),
  18. '6': (0, 0, 544, 679),
  19. '7': (0, 0, 510, 696),
  20. '8': (0, 0, 569, 689),
  21. '9': (0, 0, 561, 689),
  22. # '(': (0, -128, 290, 747),
  23. # ')': (0, -128, 290, 747),
  24. '-': (0, 0, 465, 347),
  25. '+': (0, 0, 495, 519),
  26. '*': (0, 0, 444, 481),
  27. }
  28. try:
  29. r = sess.get(ur

题目把输入的每一个字符转为ascii码,然后把ascii码的二进制中1的数目转化一下作为杠的数目再加个点,比如[2,3,4]变成--.---.----.

  1. var t = a.pop();
  2. r = r + "-".repeat(t) + ".";

观察发现转化x = 1 + j + (input_len - 1 - i) * 8有类似进位的性质,而且x达到最大值时i为0。
title

首先把点和杠换成数组:

  1. with open('instructions.txt') as f:
  2. data = [len(x) for x in f.read().strip()[:-1].split('.')]

找到最大值x
可以计算j = (x - 1) % 8, i = 0
input_len = (x - j - 1) // 8 + i + 1
然后就可以计算所有数字对应的j和i了

脚本:

  1. with open('instructions.txt') as f:
  2. data = [len(x) for x in f.read().strip()[:-1].split('.')]
  3. # x = 1 + j + (input_len - 1 - i) * 8
  4. x = max(data)
  5. j = (x - 1) % 8
  6. i = 0
  7. input_len = (x - j - 1) // 8 + i + 1
  8. output = [0] * input_len
  9. for x in data:
  10. j = (x - 1) % 8
  11. i = -((x - j - 1) // 8 - input_len + 1)
  12. output[i] |= 1 << j
  13. print(bytes(output).decode())

title

一个切碎的二维码。把不确定的爆破就好了。

  1. import itertools
  2. import os
  3. from PIL import Image
  4. import concurrent.futures
  5. import random
  6. import string
  7. from pyzbar.pyzbar import decode as qrdecode
  8. # 0 9 11 5 6 2 16 25 15 26 3 4 10 20 19 21 7 8 1 22 23 24 18 14 12 13 17
  9. count = 0
  10. chrset = string.ascii_lowercase + string.digits
  11. for v6, v15 in itertools.permutations([6, 15]):
  12. for v2, v16, v25 in itertools.permutations([2, 16, 25]):
  13. for v4, v20, v21 in itertools.permutations([4, 20, 21]):
  14. for v10, v19 in itertools.permutations([10, 19]):
  15. for v8, v14 in itertools.permutations([8, 14]):
  16. for v1, v18 in itertools.permutations([1, 18]):
  17. for v22, v23, v24 in itertools.permutations([4, 22, 23, 24], 3):
  18. group = [
  19. 0, 9, 11, 5, v6, v2, v16, v25, v15, 26, 3, v4,
  20. v10, v20, v19, v21, 7, v8, v1, v22, v23, v24,
<html>
<head>
  <meta charset="UTF-8">
  <style>
  body > * {
    margin-top: 5rem;
  }
  body {
    display: flex;
    flex-flow: column;
    margin: 0 auto;
    width: 500px;
  }
  div {
    flex: 1 0;
    align-items: flex-end;
  }
  textarea {
    width: 100%;
    flex: 5 0;
    height: 10rem;
  }
  </style>
</head>
<body>
  <div>
    <h1>🌗 🚀 👽 📡 🌓</h1>
    <p>Find <i>x</i>, such that ƒ(<i>x</i>) = <i>x</i></p>
    <textarea id="input" value="" type="text" onInput="check()"></textarea>
    <div id="result"></div>
  </div>
<script>
function check() {
  var i = input.value.replace(/\s/g, '');
  if (i == "") {
    result.innerText = "";
  } else {
    var t = f(i);
    if (t == i) {
      result.innerText = "good!";
    } else {
      result.innerText = "bad! (" + t + " != " + i + ")";
    }
  }
}

function f(x) {
  if ((x.substr(0, 2) == '🚀') && (x.slice(-2) == '🚀')) {
    return x.slice(2, -2);
  }
  if (x.substr(0, 2) == '👽') {
    return '🚀' + f(x.slice(2));
  }
  if (x.s

https://hitcon.org/2015/ENT/PDF/Power%20Analysis%20Attacks_JP,%20YH.pdf

脆弱性主要来自第一轮AddRoundKey和SubBytes和ShiftRows

假设的密钥中的某一个字节和明文的对应位置异或再查找SBOX,hamming weight计算出这个过程中产生的假设的能量。假设的能量和真实的能量计算pearson相关系数(绝对值),假设的密钥变化时相关系数最大时,能量变化最接近,假设的密钥就是正确的。再用相同的方法破解出完整的密钥。

然而我并不会jwe aes 128 gcm解密,以为算错了,赛后看wp才知道怎么解密。TAT

  1. import json
  2. from base64 import urlsafe_b64decode
  3. from binascii import hexlify
  4. import numpy as np
  5. from Crypto.Cipher import AES
  6. from cryptography.hazmat.backends import default_backend
  7. from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
  8. from scipy.stats import pearsonr
  9. SBOX = [
  10. 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
  11. 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
  12. 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
  13. 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x

下载得到五个有关联的excel表。
通过题目可以得到的信息是:登陆者职业是Captain,姓Yakubovics。由于不知道密码,所以需要通过重置密码的方式的方式登陆。在重置页面中得知我们需要提供以下这些信息title
查看excel表发现五个表中的数据都存在关联性。titletitle
因此将所有互相关联的数据都移到同一张表上。得到下表title
利用筛选选出所有职业为Captain的人的信息,总共有61个……然后不停的试找到正确数据title
在重置成功的页面中查看源代码得到flag。

对RSA的公共模数攻击
原理:设m为信息明文,两个加密公钥为e1和e2,公共模数是n,有
title如果攻击者得到了n、e1、e2、C1、C2,就可以得到m,因为e1与e2互质,故用欧几里得算法能够找到x和y,满足x^e1+y^e2=1,假设x为负数,需再使用欧几里得算法来计算1/c1,
title
本题目直接提供了公共模数n,公钥e1和e2以及密文c1和c2.因此可以直接用python代码求解:
title