西湖论剑CTF2019

Crypto

哈夫曼之谜

11317931-eaf35561b43e637c.png
哈夫曼.png

下载下来就一个文件,里面全是0101和一些字符。
搜索哈夫曼,了解到哈夫曼压缩时用到的哈夫曼树
猜测下面的字符代表频率。
哈夫曼树建立过程如下

11317931-e5490e4457f672dc.gif
哈夫曼树建立.gif

字符不多,直接在草稿纸上手写。
11317931-f1e18b187fb40c0f.jpg
哈夫曼手写.jpg

圆圈内就是构建好后对应字符的 哈夫曼编码
在建立过程中,对于频率相同的字符在不同程序上排序的前后顺序可能不同,所以存在相同频率的字符哈夫曼编码不同。比如字符5和字符d的频率都是9,则字符d的哈夫曼编码可以是01,也可以是10。
然后对上面的01串进行解码,一般是以 flag{ 开头,所以前几个字符的哈夫曼编码可以确定下来。
但字符5和字符d的无法确定,所以得到两个flag。
flag{ddf5dfd0f05550500a5af55dd0d5d0ad}
flag{55fd5f50f0ddd0d00adafdd5505d50a5}
都提交上去就可以了


Hardgame

11317931-d7e829456b91a7fe.png
Hardgame.png

有三个flag,三段加密。

flag1

加密如下

11317931-708694af1566b6a8.png
Hardgame-flag1.png

RSA加密,由于e只有2,相当于把明文m平方而已,得到的c也比n小很多。
尝试把c开根号看能否得到明文。
一般的python开根号方法精度较低,对大整数开出来的根号准确度低。
发现使用 gmpy2库可以对大整数开根号。

import gmpy2
import libnum
c = 9217979941366220275377875095861710925207028551771520610387238734819759256223080175603032167658086669886661302962985046348865181740591251321966682848536331583243529
m = gmpy2.isqrt(c)
m = int(m)
m_text = libnum.n2s(m)
print(m_text)

得到flag1flag1{Th1s_i5_wHat_You_ne3d_FirsT}

flag2

加密过程是DES-ECB-PKCS5,密钥是随机的8字节的大写字母

DES ECB(电子密本方式)其实非常简单,就是将数据按照8个字节一段进行DES加密或解密得到一段段的8个字节的密文或者明文,最后一段不足8个字节(一般补0或者F),按照需求补足8个字节进行计算(并行计算),之后按照顺序将计算所得的数据连在一起即可,各段数据之间互不影响。


11317931-afea7db741a20784.png
ECB.png

填充使用的是PKCS5,就是全部填充到8字节,后面缺几位就填几
如:后面缺4个字节,就填04040404;
8个字节都是空,就填0808080808080808


11317931-9b67ed763a5f42f9.png
PKCS5.png

该算法对很多行明文按行分开加密,密钥是8字节,ECB加密是8字节一组,如果遇到空的8字节,就会出现填充后明文为0808080808080808与密文段进行异或。

截取各行密文的后8字节,统计发现ea9c3c12181a1e8216d0aa455a272fde都出现过多次。
将密文放进hashcat进行爆破

hashcat64.exe -a 3 -m 14000 d33ad316eb246e5c:0808080808080808 -w 3 -O ?u?u?u?u?u?u?u?u
hashcat64.exe -a 3 -m 14000 ea9c3c12181a1e82:0808080808080808 -w 3 -O ?u?u?u?u?u?u?u?u

11317931-0079a18166a71942.png
flag2.png

d33ad316eb246e5c解不出来
ea9c3c12181a1e82很快可得到密钥为 JFRYOMPR

然后解密脚本如下

from pyDes import *

Des_Key = "JFRYOMPR"
def DesDecrypt(str):
    k = des(Des_Key, ECB, pad=None, padmode=PAD_PKCS5)
    DecryptStr = k.decrypt(str.decode('hex'))
    return DecryptStr

with open('enc.txt','r') as fe:
    for line in fe.readlines():
        print DesDecrypt(line.strip('\n'))

得到flag2flag2{Fuck_Y0u_cAn_Ge7_Se3ond}

再看最终的flag
用的是rsa加密
n放到factordb无法解密
e也足够大
这里的加密用了类似于CBC的方式,区别在于先加密再异或
但分组长度过短,2字节一组
所以可以构建一个明文于密文的对应字典,通过查找的方式找回原文
且由于是先加密后异或,所以可以从后往前按顺序找出每个分组异或前的加密结果

解密脚本如下

#!usr/bin/env python
# -*- coding: utf-8 -*-
import base64
import binascii
import string
import libnum
from Crypto.Util import number
from Crypto.Util.strxor import strxor

n=0x834b44a67ea419e1c3e665cedf7790ebc5fb013e2304861b667232e7ec1cae53eb253639b348a6702561671a5c5c9105eacd5d48de51427fc49f22ed2d9b60f98c50713ac95f2ac324fa58b90e0c07ab688becb771d92224be68474586376a4cd9a0ea96d5584184cbb7ad3889fd6c1a4ae3791e67a4ee6f220491abbbda2006addc6032999238cc010df759c868485522ee17e520569b7e746b0c770065f4622894afcfd46257b7c3646f15d65d561ab8e22e4f03cfbfa53ec4109115feeced84c398286bb79c58a7d640a2faec2c50285558d6b11d8ebc25eae6ece9c418dd795c0c11f459c815582c059935028cafb09b6603cc44a48f3823d0aeda73fec7
e=0x9ae923
c="L+HK7Ksu+PoVJZBnIriWufZgKFH1APFFLFnKIf7OFjlBHRAk
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值