NKCTF2024 re VM?VM!WP

逻辑似乎很简单(个鬼啊)

这个函数是把输入的字符转化为二进制并倒序存储

sub_1570太大了加载不出来,应该是加密的主逻辑,目的是需要输出1

可以通过删除栈的方法强行转化伪代码

首先删掉这部分

9A0改小点

这个也是

栈这里U一下再P

像是虚拟机的分发器,unk_4018是类似opcode的大坨数据

好像有几十万

实际上是一个2324*2324的像素图,在上面进行染色

cable management | /den/face0xff/writeupsicon-default.png?t=N7T8https://ctf.0xff.re/2022/dicectf_2022/cable_management

【游戏框架系列】Wireworld元胞自动机 - 知乎【多图预警】本文含有大量图片写在前面这次实现的是Wireworld元胞自动机,相关资料如下: 维基:Wireworld - Wikipedia 介绍:WireworldFlash模拟:Wireworld Player (Flash) 如何实现简单的计算机:The Wireworld…icon-default.png?t=N7T8https://zhuanlan.zhihu.com/p/25593938

根据资料我才知道,这其实是在模拟Wireworld元胞自动机

组成:

  1. 导体
  2. 电子头
  3. 电子尾

每代变化:

  1. 空→空
  2. 电子头→电子尾
  3. 电子尾→导体
  4. 当仅有一个或仅有两个电子头的邻居是导体时,导体→电子头

对应着理解,0xCD就是导线

0xEA就是电子尾,0xEC是电子头

0x11是数据注入点

0x80相当于空/消除信号

1就是终点,到达就返回1

由此根据数据绘图分析,这实际上是利用wireworld高度抽象的虚拟机

数据量太大,这里用脚本提取

#data_extract
import idaapi  
import idautils  
  
# 设置你要读取数据的起始和结束地址  
START_ADDR = 0x4018  # 替换为你的起始地址  
END_ADDR = 0x535D93  # 替换为你的结束地址  
BYTES_PER_LINE = 16  # 每行显示的字节数  
  
# 打开一个文件用于写入,如果文件不存在则创建它  
with open('output.txt', 'w') as f:  
    # 用于记录当前行已经写入了多少字节  
    bytes_written = 0  
    # 遍历指定地址范围内的每个地址  
    for ea in range(START_ADDR, END_ADDR + 1):  
        # 读取当前地址的一个字节  
        byte_value = idaapi.get_byte(ea)  
        # 将字节转换为十六进制字符串  
        hex_string = '0x{:02X}'.format(byte_value)  
        # 写入文件,并在需要时添加逗号  
        if bytes_written > 0 and bytes_written % BYTES_PER_LINE != 0:  
            f.write(',')  
        f.write(hex_string)  
        bytes_written += 1  
        # 如果当前行已经写入了足够的字节数,则换行  
        if bytes_written % BYTES_PER_LINE == 0:  
            f.write(',\n')  
  
# 文件会在脚本执行完毕后自动关闭  
print("Data has been written to output.txt")

然后绘图(来自孤恒师傅的脚本)

from PIL import Image
s = [...]
img = Image.new('RGB', (0x914, 0x914), (255, 255, 255))
pixels = img.load()
for i in range(len(s)):
    if s[i] == 0x1:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0x01_row:"+f"{i_row:X}" + "  0x01_col:"+f"{i_col:X}")
        pixels[i_row, i_col] = (255, 0, 0)

    elif s[i] == 0xEC:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0xEC_row:"+f"{i_row:X}" + "  0xEC_col:"+f"{i_col:X}")
        pixels[i_row, i_col] = (0, 0, 255)

    elif s[i] == 0x11:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0x11_row:"+f"{i_row:X}" + "  0x11_col:"+f"{i_col:X}"
        pixels[i_row, i_col] = (0, 255, 0)

    elif s[i] == 0xCD:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0xCD:"+f"{i:X}")
        pixels[i_row, i_col] = (0, 0, 0)

    elif s[i] == 0x80:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0xCD:"+f"{i:X}")
        pixels[i_row, i_col] = (255, 255, 0)
		
    elif s[i] == 0xEA:
        i_row = i // 0x914
        i_col = i % 0x914
        #print("0xCD:"+f"{i:X}")
        pixels[i_row, i_col] = (0, 255, 255)

img.save('D:\\下载\\CTF附件\\nk\\image.png')

有大量重复的图案,我们放大进行分析

乍一看难以理解,结合wireworld的规则,我们可以分析出图案蕴藏的含义

最上面就是一条畅通无阻的电线

下面很复杂,先看重复度最高的这部分,注意到不断重复的这个模块

我们用网站模拟

Wireworld Simulatoricon-default.png?t=N7T8https://danprince.github.io/wireworld/

只有一侧输入信号(即一侧1,一侧0)时,电子头会正常向下传导

但如果两边都有

信号就会消失

所以这其实是在模拟异或(逻辑门),原理是在这里

箭头所指的导线周围有三个电子头,但我们的规则是当仅有一个或仅有两个电子头的邻居是导体时,导体→电子头

因此就达到了异或的效果

图中除了大量的异或,还有别的图形

可以用相同的方法分析出这个是与

这个是或

这个则是一个二极管,像神经突触一样,只会从“突触前模”向“突触后膜”单向传导

我们可以根据这些特征把整个图分割开,由于每个输入的字符都转化为8位二进制注入(绿色就是注入点),所以我每八个循环分割一次,最后得到29块,对应29个输入的字符

输入的字符究竟是如何处理的呢?可以看到,每个绿色注入点激活的电子头会向左右两边传导,经过一个异或(输入的字符转化为倒序二进制数,这个数的每相邻两位异或)之后,与蓝色点激活的电子头再次异或,之后得到的信号就会输入下面的向右的二极管结构

也就是说,只要有一个异或结果是1(有电),电子头就会向右传导到失败点。所以我们的目标就是消除所有产生的电子头,使得上面那一条完整的电线上的电子头平安到达左侧的终点

可以看到,蓝色电子头总是在循环结构相同的位置上,代表着这个位置上电信号的1和0,将他们连接在一起就相当于组成了一个由0、1组成的key(可以脚本取key,我嫌麻烦就直接手敲了)

我们要求的flag是上面一排注入点的0/1状态,加密过程就是我之前说的一系列异或,我们期望得到的结果就是全0

由此我们可以写出解密的函数,将key与全0序列异或逆序转化成字符串

def decode(key):
    key_string = long_to_bytes(int("".join([str(i) for i in key]), 2))
    #print(key_string)
    res = [0]
    for i in range(len(key)-1):
        tmp = res[i]^key[i]
        res.append(tmp)
    #print(res)
    flag = long_to_bytes(int("".join([str(i) for i in res]), 2))
    print(flag)

但我们并不能把整段key直接放进去解密,因为整个wireworld结构被中段分割成了两半,右边(相当于前面一半)是插入了与的部分

左边是插入了或的部分

先看前半部分,与的前面有四个注入点,key第四位相当于缺失的

但反正就0和1两种情况,拿出前八位二进制试一下就会发现这一位为1的时候可以得到n(就是nkctf的开头),否则会得到a

然后第9位一直到断点前面都是连续的,可以得到第二段flag

中间这个位置比较尴尬,这四位右边是断开的,左边是个或,只要有一个满足1就能激活

中间四位排列组合一下就能凑出有意义字符

剩下的直接输入

就可以得到完整的flag了

#VM?VM!
from Crypto.Util.number import long_to_bytes
key0 = [1, 0, 1, 1, 0, 0, 1, 0]

key1 = [1, 0, 1, 1, 1, 1, 0, 1, 
1, 0, 1, 0, 0, 1, 0, 1,
1, 0, 0, 1, 1, 1, 0, 0,
1, 0, 1, 0, 1, 0, 1, 0, 
1, 0, 0, 0, 1, 1, 0, 1, 
1, 0, 0, 1, 1, 0, 0, 1, 
1, 0, 1, 1, 1, 0, 1, 1, 
1, 1, 1, 1, 0, 1, 1, 0, 
1, 0, 1, 0, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 0, 0, 1, 
1, 0, 1, 1, 0, 0, 0, 1]

key2 = [0, 1, 1, 1, 0, 1, 
1, 1, 
1, 0, 
1, 1, 0, 1, 0, 0]

key3 = [1, 0, 1, 0, 1, 1, 0, 0, 
1, 1, 1, 0, 0, 0, 0, 1, 
0, 1, 0, 1, 0, 0, 1, 1, 
1, 0, 0, 1, 0, 1, 0, 1, 
1, 1, 1, 0, 0, 0, 0, 1, 
1, 0, 1, 1, 0, 0, 1, 0, 
0, 1, 0, 1, 0, 0, 0, 0, 
1, 0, 0, 1, 1, 1, 0, 0, 
1, 1, 1, 0, 0, 0, 0, 1, 
1, 0, 1, 0, 1, 0, 0, 1, 
1, 0, 1, 1, 0, 0, 0, 1, 
1, 1, 0, 1, 0, 0, 0, 1, 
1, 1, 0, 0, 1, 1, 0, 0, 
0, 1, 1, 0, 0, 0, 1, 1, 
1, 0, 0, 0, 0, 1, 1, 0]
def decode(key):
    key_string = long_to_bytes(int("".join([str(i) for i in key]), 2))
    #print(key_string)
    res = [0]
    for i in range(len(key)-1):
        tmp = res[i]^key[i]
        res.append(tmp)
    #print(res)
    flag = long_to_bytes(int("".join([str(i) for i in res]), 2))
    print(flag)
decode(key0)
decode(key1)
decode(key2)
decode(key3)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

通讯录(顺序表的应用)

文章目录 顺序表思想实现通讯录头文件接口函数主函数 顺序表思想实现通讯录 实现通讯录前,我们考虑一下,通讯录需要包含什么内容? 联系人,联系人需要包含姓名年龄电话性别这3种基本信息。 我们知道顺序表实质是个数组&#xff…

【C++】C++中的list

一、介绍 官方给的 list的文档介绍 简单来说就是: list是可以在常数范围内在任意位置进行插入和删除的序列式容器,并且该容器可以前后双向迭代。list的底层是双向链表结构,双向链表中每个元素存储在互不相关的独立节点中,在节点中…

浅谈TCP(2):流量控制与拥塞控制

上文浅谈TCP(1):状态机与重传机制介绍了TCP的状态机与重传机制。本文介绍流量控制(Flow Control,简称流控)与拥塞控制(Congestion Control)。TCP依此保障网络的QOS(Quali…

【Leetcode每日一题】 递归 - 求根节点到叶节点数字之和(难度⭐⭐)(50)

1. 题目解析 题目链接:814. 二叉树剪枝 这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。 2.算法原理 想象一下,你有一堆层层叠叠的积木,你想从底部开始,把那些标记为0的积木拿走。如…

【QT+QGIS跨平台编译】056:【PDAL+Qt跨平台编译】(pdalcpp错误处理)

点击查看专栏目录 文章目录 一、报错信息:二、原因分析三、解决思路四、原版FileUtils.cpp五、修改后的FileUtils.cpp一、报错信息: ① exists is unavaiable: introduced in macOS 10.15 ② create_directory is unavaiable: introduced in macOS 10.15 ③ create_director…

BCLinux-for-Euler配置本地yum源

稍微吐槽一句…… 在这片土地上,国产化软件的大潮正在滚滚而来,虽然都不是真正意义上的国产化,但是至少壳是国产的~~~ 之前使用的Centos7的系统,现在都要求统一换成BCLinux-for-Euler。说实话换了之后不太适应,好多用习…

练习实践-TLS02-会话恢复的两种形式-Session ID/SessionTicket

参考来源: 书籍:深入浅出https-从原理到实战(作者:虞卫东) 抓包分析文件可下载,来自github上的作者上传资源 会话恢复机制的背景 当客户端和服务器端握手成功,建立了一个完整的 TLS 连接&…

刷题之Leetcode35题(超级详细)

35.搜索插入位置 力扣题目链接(opens new window)https://leetcode.cn/problems/search-insert-position/ 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 你可…

ChatGPT 与 OpenAI 的现代生成式 AI(下)

原文:Modern Generative AI with ChatGPT and OpenAI Models 译者:飞龙 协议:CC BY-NC-SA 4.0 七、通过 ChatGPT 掌握营销技巧 在本章中,我们将重点介绍营销人员如何利用 ChatGPT,在这一领域中查看 ChatGPT 的主要用例…

jvisualvm 使用教程

之前看过 jvisualvm,但是那个时候对 JVM 并不是很熟悉,后面看了下八股文,看了下 JVM 的相关知识之后,发现多了解点 JVM 的东西,对我们 CRUD 其实是有指导意义的,就比如我们通常会 new 一堆的没有用到的对象…

读所罗门的密码笔记10_寒武纪国家与城堡国家

1. DARPA 1.1. DARPA仍然是世界领先的尖端高科技研究推动者之一,资助研发人员开展各个领域的前沿研究,从自动驾驶汽车到植入式神经芯片,从复杂的系统分析(比如分析气候变化)到网络安全,无一…

31. 下一个排列 —— LeetCode (python) [PS: LeetCode 运行环境疑似出错]

# encoding utf-8 # 开发者:xxx # 开发时间: 20:26 # "Stay hungry,stay foolish."class Solution(object):def nextPermutation(self, nums):import itertoolsl len(nums)a tuple(nums)nums.sort()permutations_lst list(ite…

DDD 的四层领域模型是怎样的?包含哪些基础概念?

DDD的四层领域模型如下所示: 展现层:这一层负责向用户显示信息和解释用户命令,完成前端界面逻辑。并将用户请求传递给应用层。应用层:这一层是很薄的一层,负责协调领域层中的领域对象,组成具体应用场景。应…

JAVA JVM内存模型和GC分配和回收

Java 的JVM简介 JVM是(Java Virtual Machine)Java虚拟机的缩写。 JVM是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。 ​ 在Java程序运行时,所有的.class类需要加载到JVM中才能执行代码逻辑。不…

Python环境下基于离散小波变换的信号降噪方法

Mallat创造了小波分析中的经典理论之一,即多分辨率分析的概念。后来,在Mallat与Meyer的共同努力之下,他们又在这一理论的基础上发明了离散小波变换的快速算法,这就是Mallat塔式算法,这种算法可以大量减少计算时间。在之…

解锁未来:大模型GPT的应用架构与创新实践

在人工智能的黄金时代,大模型如GPT(Generative Pre-trained Transformer)已成为技术创新和应用发展的前沿。它不仅重新定义了人机交互的方式,还在多个领域内展现出了巨大的应用潜力。本文将深入探讨大模型GPT的应用架构&#xff0…

深入解析:链游、DApp、公链、NFT与交易所开发的全景图

随着数字货币和区块链技术的迅速发展,链游开发、DApp开发、公链开发、NFT开发以及交易所开发等领域吸引了越来越多的关注。本文将以3000字的篇幅,对这些领域进行详细解析,探讨它们的意义、应用场景以及未来发展趋势。 链游开发(Bl…

基于keepalived+gtid+双vip半同步主从复制的MySQL高性能集群

项目名称:基于keepalivedgtid双vip半同步主从复制的MySQL高性能集群 目录 项目名称:基于keepalivedgtid双vip半同步主从复制的MySQL高性能集群 项目规划图 1.配置4台MySQL服务器(1台master,2台slave,1台backup&a…

光伏无人机:绿色能源与航空技术的融合创新

在可再生能源和无人机技术快速发展的背景下,光伏无人机作为一种新兴的绿色航空器,正逐渐展现出其独特的优势和广阔的应用前景。本文将深入探讨光伏无人机的原理、优势以及其在多个领域的应用,展望其未来的发展趋势。 一、光伏无人机的原理 光…

基于微信小程序的外卖管理系统的设计与实现(论文+源码)_kaic

摘 要 互联网发展至今,无论是其理论还是技术都已经成熟,而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播,搭配信息管理工具可以很好地为人们提供服务。针对高校教师成果信息管理混乱,出错率高,信息安全…