Hack the Box CTF 比赛 简单难度 XOR 密码学题目 Crypto 流程| Multikey Walkthrough

news2024/9/25 9:38:15

这是近期参加HTB夺旗战时遇到的一道难度为简单的密码学Crypto题目。但是我觉得挺有意思,就做下记录。

1. 题目:


题干没有太多的内容,就是一段python程序,和一个output的加密结果,如下。

Python:

import os

flag = open("flag.txt", "rb").read()

def genkeys(n):
    keys = [os.urandom(5) for _ in range(n)]
    return keys

def encrypt(keys, flag):
    for key in keys:
        flag = bytes([a ^ b for a, b in zip(flag, key * (len(flag)+5//5))])
        print(fl)
    return flag

keys = genkeys(1955) # with this many keys, this is totally secure
print(encrypt(keys, flag).hex())


Output.txt:

cf7bfbb7e9b770ceffd2f51c8da0e1fe70d7ffbee370cda4bcf470d4f8e3fe70daf8ffd8448ab5b8d84989bed2b370cafde1eb56e6b8bcea4ae6a1b9e44788a2beb810c4

有兴趣的朋友可以自己先做一做,flag的固定格式是(只是格式,flag长度未知):HTB{f4k3_fl4g_f0r_t3st1ng}

2. 通读程序:


首先通读python程序,简单易懂。

第一步,从flag.txt里读取flag原文。

第二步,genkeys( )是一个利用urandom每次生成5个随机字符串作为key的函数。程序中 n = 1955,表示 keys 为一个拥有1955组 key 的 list, 而每组都有5个key。 (这里如果难以理解可以自己打印一下keys,或者将n改为一个较小值)

第三步,encrypt( )是一个利用XOR生成的keys对flag原文进行加密的函数。原理是将flag的每位不断和5位key做XOR运算进行加密,直到做完1955组随机生成的key。

注意: 程序中的 key * (len(flag)+5//5)) 这一步只是为了确保 key的长度永远比flag长,每一位flag都能与keys加密。所做的操作就是不断重复5位key。 
例如:生成的5位key为 abcde,在经历 key * (len(flag)+5//5))之后, key 变为 abcdeabcdeabcde....

总结,这就是对flag进行加密的源程序。我们的目标就是将output.txt里的密文根据python加密程序逆向求出原文。

3. 解题思路


这题的核心思路就是他的加密算法 XOR。有两个核心的算法基础:

3.1 核心一:


XOR运算符为 \oplus,Flag的原文是 P,加密的1955组密钥为:Key_1, Key_2, Key_3,...... , Key_{1955}。加密的运算过程可以表示为:
 

P \oplus Key_1 \oplus Key_2 \oplus Key_3 \oplus....... \oplus Key_{1955}
 

看起来 Flag经历了如此多的XOR运算,几乎无法进行还原。事实上,XOR具有结合律的特性,即:

a \oplus b \oplus c = a \oplus (b \oplus c) = (a \oplus b) \oplus c
 

因此,加密过程可简化为:

P \oplus ( Key_1 \oplus Key_2 \oplus Key_3 \oplus....... \oplus Key_{1955} )

整个加密过程可以看为,所有的key先做XOR运算,得出一个结果后,再与flag(P)进行一次XOR运算。因此,看起来flag和key做了1955次XOR运算。实际上如果把所有key的XOR运算看成一个整体,作为一个终极无敌key,flag将只会和这个终极无敌key进行 一次 XOR运算。

3.2 核心二:


XOR运算的逆运算是它本身,也就是说两次异或同一个数最后结果不变,即 :

\left ( a \oplus b\right ) \oplus b = a
 由核心一可知,密文(C)可以由明文(P)与终极无敌 Key 做一次 XOR得到,即(1):

C = P \oplus Key_{wudi} \left ( 1 \right )


可得到:

Key_{wudi} = P \oplus C \left ( 2 \right )
 

P = C \oplus Key_{wudi} \left ( 3 \right )


整理一下思路,现在我们有 flag 的密文,以及HTB{ } 几位明文。我们可以通过已知的几位明文(HTB{ })和密文的对应关系求出密钥(一共五位)即(2)。然后才能解密密文(3)。 

密文一共是136位,由于密文用bytes( ) 和hex( ) 被转换为十六进制,两位十六进制对应一位ASCII码,所以相对应的ASCII码明文为68位。假设68位明文全部为Flag的内容,我们会发现一个问题,根据 HTB{ 四位明文字符和他们的密文,我们可以通过XOR运算得出前四位的密钥(key),而 是第68位,对应的是第三位密钥而不是第五位密钥。因此我们只能得出四位密钥。

但是4位总比1位没有好吧,走一步看一步。
我们先把四位密钥算出来。

4. 操作


4.1 将16进制密文转化为10进制


因为过程涉及16进制和ASCII码还有XOR的运算,我选择使用人类熟悉的十进制,当然直接用16进制也是可以的。这一步,是将output中每一位对应的16进制分开(并转换成10进制)。

out = "cf7bfbb7e9b770ceffd2f51c8da0e1fe70d7ffbee370cda4bcf470d4f8e3fe70daf8ffd8448ab5b8d84989bed2b370cafde1eb56e6b8bcea4ae6a1b9e44788a2beb810c4"
d = []

for i in range(1,136,2):
    h = out[i-1]+out[i]
    d.append (int(h, base=16))

print(d)

---------------------------------------------------------------------------------

Result:
[207, 123, 251, 183, 233, 183, 112, 206, 255, 210, 245, 28, 141, 160, 225, 254, 112, 215, 255, 190, 227, 112, 205, 164, 188, 244, 112, 212, 248, 227, 254, 112, 218, 248, 255, 216, 68, 138, 181, 184, 216, 73, 137, 190, 210, 179, 112, 202, 253, 225, 235, 86, 230, 184, 188, 234, 74, 230, 161, 185, 228, 71, 136, 162, 190, 184, 16, 196]


这里输出的结果是10进制的密文,每一个元素对应明文的一个字符。例如:明文里的 H 对应 207,T 对应 123,B 对应 251,{ 对应 183,} 对应 196。


4.2. 计算超级无敌Key


将明文 的每一位 和 对应的密文的每一位做 XOR 运算,将得到超级无敌Key的前四位

flag = [72, 84, 66, 123, 125]     ## HTB{}的十进制ASCII码
out = [207, 123, 251, 183, 196]   ## HTB{}的十进制对应密文

FakeSuperkey = [a ^ b for a, b in zip(flag,out)]
print(FakeSuperkey)

---------------------------------------------------------------------------------

Result:
[135, 47, 185, 204, 185]


我们注意到 超级无敌Key中有两个185,原因也很简单,因为 明文 B 和 明文 } 都是用超级无敌Key中的第三位进行加密的。

现在我们有了四位 超级无敌Key,按理来说可以还原 \frac{4}{5} 的明文了。说不定可以从还原的明文中找到规律,得到最后一位Key。


4.3. 还原\frac{4}{5}个明文


我们假设超级无敌Key的最后一位和第三位一模一样,即都为185。先假设的超级无敌Key为步骤二中的 [135, 47, 185, 204, 185],但你我都清楚,这个第五位是假的,那么还原的时候明文中所有是5的倍数为的字符都是假的。
但是,我们就是要这么干!

out = [207, 123, 251, 183, 233, 183, 112, 206, 255, 210, 245, 28, 141, 160, 225, 254, 112, 215, 255, 190, 227, 112, 205, 164, 188, 244, 112, 212, 248, 227, 254, 112, 218, 248, 255, 216, 68, 138, 181, 184, 216, 73, 137, 190, 210, 179, 112, 202, 253, 225, 235, 86, 230, 184, 188, 234, 74, 230, 161, 185, 228, 71, 136, 162, 190, 184, 16, 196]    

## 68 位密文

FakeSuperkey = [135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185, 135, 47, 185, 204, 185]  

## 五位密钥被key * (len(flag)+5//5))处理过后将变得比密文长,长多少无所谓,因为会被zip掉。


out = [a ^ b for a, b in zip(out,FakeSuperkey)]

ass = ""
j = 0
for item in out:
    j += 1
    if j % 5 == 0:
        ass += '*'
    else:
        ass += chr(item)

print(ass)

---------------------------------------------------------------------------------

Result:
HTB{*0_w3*r34l*y_n3*d_th*s_m4*y_c4*_k3y*_f0r*4_s1*ly_t*me_m*ch1n*??}

芜湖!\frac{4}{5}个flag以及拿到手了。观察一下旗子的明文,发现是用数字替换单词字幕的惯用手法。比如 i 替换为 1。而最后三个单词很有辨识度,是 silly time machine 的变形。我们只需要算出任意一个 * 号处的 Key 即可。

5. 夺旗!


这里我们使用time中的 i,在明文中应该是 1 (ASCII 码为 49),数出他在密文中对应的位置 (188)。因此我们现在使用 HTB{1 作为明文 (72, 84, 66, 123 ,49是他们的ASCII码)以及他们对应的十进制密文 (207, 123, 251, 183, 188),来制作真正的终极无敌Key。

flag = [72, 84, 66, 123 ,49]
out = [207, 123, 251, 183, 188]

RealSuperKey = [a ^ b for a, b in zip(flag,out)]

print(RealSuperKey)

---------------------------------------------------------------------------------

Result:
[135, 47, 185, 204, 141]


拿到终极无敌Key的我双手热得发烫!!!
将终极无敌Key的五个密钥复制成比flag长后,开始最终揭秘!!!!!

out = [207, 123, 251, 183, 233, 183, 112, 206, 255, 210, 245, 28, 141, 160, 225, 254, 112, 215, 255, 190, 227, 112, 205, 164, 188, 244, 112, 212, 248, 227, 254, 112, 218, 248, 255, 216, 68, 138, 181, 184, 216, 73, 137, 190, 210, 179, 112, 202, 253, 225, 235, 86, 230, 184, 188, 234, 74, 230, 161, 185, 228, 71, 136, 162, 190, 184, 16, 196]

key = [135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141, 135, 47, 185, 204, 141]

out = [a ^ b for a, b in zip(out,key)]

ass = ""
for item in out:
    ass += chr(item)
print(ass)

---------------------------------------------------------------------------------

Result:
HTB{d0_w3_r34lly_n33d_th1s_m4ny_c4r_k3y5_f0r_4_s1lly_t1me_m4ch1n3??}


6. 结语:


Marty McFly: Do we really need this many car keys for a silly time machine??
Marty McFly: No, we don't.


以上。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/130097.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构】手推堆实现,拳打堆排序,脚踩Top-k

目录一.完全二叉树的顺序结构二.堆的概念及结构三.堆的实现1.堆向下调整2.向下调整建堆3.向下调整建堆时间复杂度4.堆的插入(向上调整)5.向上调整建堆6.向上调整建堆时间复杂度7.堆的删除8.堆的代码实现四.Top-K问题五.堆排序一.完全二叉树的顺序结构 堆…

GPIO实验

一、GPIO简介 GPIO(General-purpose input/output)即通用型输入输出,GPIO可以控制连接在其之上的引脚实现信号的输入和输出 芯片的引脚与外部设备相连,从而实现与外部硬件设备的通讯、控制及信号采集等功能 实验步骤1. 通过电路…

第十七讲:神州三层交换机DHCP服务器配置

DHCP是基于Client-Server模式的协议,DHCP客户机向DHCP服务器索取网络地址及配置参数;服务器为客户机提供网络地址及配置参数;当DHCP客户机和DHCP服务器不在同一子网时,需要由DHCP中继为DHCP客户机和DHCP服务器传递DHCP…

java企业通知小程序微信消息推送小程序企业消息通知系统网站源码

简介 本系统主要是利用小程序和springboot开发的企业分组消息推送,主要是员工关注小程序,由分组领导创建消息主体并设置消息提醒时间,利用微信的消息模板对选定的员工进行消息提醒推送。比如公司的技术部需要在11月3号早上8点举行晨会&#…

【Java编程进阶】面向对象思想初识

推荐学习专栏:Java 编程进阶之路【从入门到精通】 文章目录1. 面向对象初识2. 类和对象2.1 类的定义2.2 对象的创建和使用3. 构造方法4. 方法重载5. static 关键字5.1 static 方法5.2 static 变量6. 对象的引用和 this7. 总结1. 面向对象初识 之前我们学习了 C 语言…

P2367 语文成绩和P5542 Painting The Barn S(一维和二维差分)

目录 前言 一、P2367 语文成绩 二、P5542 Painting The Barn S 前言 图文详解一维差分 图文详解二维差分 一、P2367 语文成绩 题目背景: 语文考试结束了,成绩还是一如既往地有问题。 题目描述: 语文老师总是写错成绩,所以当…

关于C语言中内存分配

一、static在C语言里面可以用来修饰变量,也可以用来修饰函数。 1、 先看用来修饰变量的时候。变量在C语言里面可分为存在全局数据区、栈和堆里。 其实我们平时所说的堆栈是栈而不是堆,不要弄混。 例如:在file.c中 int a ; int main() { int b…

如何在 Python 中自动化处理 Excel 表格?

考虑一个场景,要求在网站上为 30,000 名员工创建一个帐户。手动重复执行此任务会非常枯燥乏味。此外,这将花费太多时间,这不是一个明智的决定。 现在想象一下从事数据输入工作的员工的生活。他们的工作是从 Excel 表格中获取数据并将其插入其…

CSS 实现灯笼动画,祝大家元旦快乐

前言 👏CSS 实现大红灯笼动画,祝大家元旦快乐,2023越来越棒!速速来Get吧~ 🥇文末分享源代码。记得点赞关注收藏! 1.实现效果 2.实现步骤 定义一个灯笼的背景色bg,线条颜色lineColor :root …

数字时代下, 企业如何保证数据的安全

随着全球数字化进程的蓬勃发展,在互联网时代下技术和数据深度融合的数字经济模式为许多行业带来了更大创收。数据也已经成为了五大核心生产要素之一,驱动着国家、社会、企业全方位高速发展。“迎接数字时代,激活数据要素潜能,推进…

四、 Spring-MVC

MVC MVC :Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计规范。本质上也是一种解耦。 Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常…

使用CLIP构建视频搜索引擎

CLIP(Contrastive Language-Image Pre-training)是一种机器学习技术,它可以准确理解和分类图像和自然语言文本,这对图像和语言处理具有深远的影响,并且已经被用作流行的扩散模型DALL-E的底层机制。在这篇文章中,我们将介绍如何调整…

再获权威认可 百分点科技入选Forrester AI/ML平台主流供应商

近日,全球领先的研究和咨询公司Forrester发布了2022年第四季度中国AI/ML(人工智能/机器学习)平台报告《The AI/ML Platform Landscape In China, Q4 2022》,系统分析了AI/ML平台市场的业务价值、市场成熟度及市场动态,…

python基础语法24-多线程实操

上一节说了多线程的理论知识,今天来实际操作一下。 1.创建线程 python中有2中方法创建线程,分别为函数和类继承 (1).使用函数来创建线程 调用 _thread 模块中的start_new_thread()函数来产生新线程。语法如下: _thread.start_new_thread ( function, args[, kwargs] ) 参数说…

保护小程序,防止反编译:打造不怕反编译的小程序

保护小程序,防止反编译 打造不怕反编译的小程序 这几年,小程序、小游戏,非常火。 业内人都知道,小程序或小游戏,就是H5应用,就是htmlJS。这类应用,反编译很容易,网上就有很多方法教程。 对小…

我坦白→低代码功能我有,SQL练习题、数据可视化、数据填充助你高效

简介 今天勇哥看了一下群里的聊天信息,大家都在说低代码平台,见大家对于低代码这么热衷的情况下,勇哥也不藏着掖着了,先放几个低代码功能出来,给大家玩一玩,更多的功能敬请期待。 帮勇哥投个票&#xff1…

Docker进阶 — 一文掌握Docker基础

Docker进阶 — 一文掌握Docker基础 文章目录Docker进阶 --- 一文掌握Docker基础一、初识 Docker1. 什么是Docker2. Docker架构3. DockerHub4. Docker运行模式5. Docker和虚拟机的区别二、Docker 的安装1. Linux安装Docker2. Window 安装Docker环境配置1. 开启 Hyper-V服务2. 安…

五款炫酷精美动态登录页面,彩虹气泡动态云层深海灯光水母炫酷星空蛛网HTMLCSS源码

完整源码详见 微信公众号&#xff1a;创享日记 对话框发送&#xff1a;登录页面 获取HTMLCSSjs等源码文件 一、彩虹气泡登录页面 效果图&#xff1a; HTML源码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-…

linux 下coredump 生成及调试分析

Windows环境崩溃问题&#xff08;dump&#xff09;可根据vs调试或windbg工具查看.linux环境崩溃文件为core文件&#xff0c;可以使用gdb进行调试分析。 前提&#xff1a;都是都是用了root权限的用户操作。 1.生成core文件的前提 产生coredump的条件&#xff0c;首先需要确认…

优化改进YOLOv5算法之添加RepVGG模块(超详细)

在前面的文章中已经详细介绍了在本机上安装YOLOv5的教程&#xff0c;安装YOLOv5可参考前面的文章YOLOv5训练自己的数据集(超详细)https://blog.csdn.net/qq_40716944/article/details/118188085 目录 1、RepVGG原理 1.1 模型定义 1.2 为什么要用VGG式模型 1.3 结构重参数化…