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 // 0x914i_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 // 0x914i_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 // 0x914i_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 // 0x914i_col = i % 0x914#print("0xCD:"+f"{i:X}")pixels[i_row, i_col] = (0, 0, 0)elif s[i] == 0x80:i_row = i // 0x914i_col = i % 0x914#print("0xCD:"+f"{i:X}")pixels[i_row, i_col] = (255, 255, 0)elif s[i] == 0xEA:i_row = i // 0x914i_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)

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

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

相关文章

快手2024春季招聘揭秘!最全面的Spring RESTful Web面试题大全,学会这些让你面试无压力!

随着Spring框架在构建现代Web应用中的广泛应用,对于掌握如何高效地使用Spring来创建RESTful Web服务的需求日益增长。特别是在快手这样的创新和技术驱动的公司,深入理解Spring RESTful Web服务的开发不仅是通过技术面试的关键,更是在日后的工…

DFS:深搜+回溯+剪枝解决组合问题

创作不易,感谢支持!!! 一、电话号码的组合 . - 力扣(LeetCode) class Solution { public:string hash[10]{"","","abc","def","ghi","jkl","mno","pqrs"…

爬虫部署平台crawlab使用说明

Crawlab 是一个基于 Go 语言的分布式网络爬虫管理平台,它支持 Python、Node.js、Jar、EXE 等多种类型的爬虫。 Crawlab 提供了一个可视化的界面,并且可以通过简单的配置来管理和监控爬虫程序。 以下是 Crawlab 的一些主要优点: 集中管理&am…

Naive UI n-data-table 分页试用

版本 “naive-ui”: “^2.37.3”, “ts-node”: “^10.9.2”, “typescript”: “~4.5.4”, “vue”: “^3.4.14” 官方示例 https://www.naiveui.com/zh-CN/os-theme/components/data-table#ajax-usage <template #2><!-- 展示信息 --><n-data-tableremote:col…

【flatbuffers】vs2022构建及Qt工程测试

cmake 生成,直接构建 debug或者release参考大神的例子release 构建 Build started at 17:44... 1>------ Build started: Project: flattests_cpp17, Configuration: Release Win32 ------ 2>------ Build started: Project: flathash, Configuration: Release Win32 --…

【C】leetcode力扣—— 141. 环形链表Ⅰ

目录 141. 环形链表 Ⅰ题目解题思路分析暴力求解&#xff1f;&#xff1f;快慢指针 代码 141. 环形链表 Ⅰ 题目链接: https://leetcode.cn/problems/linked-list-cycle/description/ 题目 题目 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某…

E-魔法猫咪(遇到过的题,做个笔记)

题解&#xff1a; 来自学长们思路&#xff1a; 其中一种正解是写单调队列。限制队列内的数单调递增&#xff0c;方法为每当新来的数据比当前队尾数据小时队 尾出列&#xff0c;直到能够插入当前值&#xff0c;这保证了队头永远是最小值。因此总体思路是队尾不断插入新值的同时 …

openlayers 入门教程(九):overlay 篇

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

Spring框架提供三个核心服务

1. IOC&#xff1a;控制反转服务 由“Spring容器对象”完成指定类的实例对象的创建 2. DI&#xff1a;依赖注入 由“Spring容器对象”完成指定对象的初始化的服务 3. AOP:面向切面编程 降低开发人员使用代理设计模式难度&#xff0c;开发人员只需要专注于切面类的开发即可…

vue-cli打包 nodejs内存溢出 vue2.x Last few GCs

遇到这种情况百度各种博客&#xff0c;什么改package.json里的配置&#xff0c;什么安装increase-memory-limit &#xff0c;都尝试了并没什么用处&#xff0c;最后解决方案为执行下方名单&#xff0c;再次打包就成功了&#xff1a; export NODE_OPTIONS--max_old_space_size4…

android 内存优化

什么是内存泄漏? 如果一个无用对象&#xff08;不需要再使用的对象&#xff09;仍然被其他对象持有引用&#xff0c;造成该对象无法被系统回收&#xff0c;以致该对象在堆中所占用的内存单元无法被释放而造成内存空间浪费&#xff0c;这中情况就是内存泄漏。 在Android开发中…

单元测试 mockito(二)

1.返回指定值 2.void返回值指定插桩 3.插桩的两种方式 when(obj.someMethod()).thenXxx():其中obj可以是mock对象 doXxx().wien(obj).someMethod():其中obj可以是mock/spy对象 spy对象在没有插桩时是调用真实方法的,写在when中会导致先执行一次原方法,达不到mock的目的&#x…

好物视频素材在哪找?视频素材大全app下载

创作优质视频内容不仅仅是一种艺术&#xff0c;也是一种科学&#xff0c;需要对素材的深刻理解和精心挑选。掌握了这些高清无水印视频素材&#xff0c;您就拥有了创作引人入胜视频内容的强大工具。以下是更多精选的视频素材网站&#xff0c;旨在为您的视频项目提供更广阔的视野…

Python | Leetcode Python题解之第10题正则表达式匹配

题目&#xff1a; 题解&#xff1a; class Solution:def isMatch(self, s: str, p: str) -> bool:m, n len(s), len(p)dp [False] * (n1)# 初始化dp[0] Truefor j in range(1, n1):if p[j-1] *:dp[j] dp[j-2]# 状态更新for i in range(1, m1):dp2 [False] * (n1) …

专升本--python运算符总结

运算优先级 同一个等级是没有先后顺序的&#xff0c;此外&#xff0c;赋值语言的先后问题&#xff1a; 赋值的顺序从上往下&#xff0c;同一行一般都是代表同时进行赋值&#xff0c;如图所示&#xff1a; 一.and A and B&#xff0c;若A,B有任意一个为假&#xff08;0&#x…

希尔排序和快排里的小区间优化

希尔排序 希尔排序是插入排序的优化。 当一串数是逆序时&#xff0c;那么每插入一个数&#xff0c;前面的数都会向后面挪动。 那么这是插入排序的时间复杂度&#xff0c;就会达到O(n^2) 希尔排序是对数组里的数进行预排序。 防止插入排序出现最坏的情况。 预排序&#xf…

代码随想录-图论

797.所有可能的路径&#xff1a; . - 力扣&#xff08;LeetCode&#xff09; class Solution {List<List<Integer>> ansnew LinkedList<>();List<Integer> listnew LinkedList<>();public List<List<Integer>> allPathsSourceTarg…

ABC318 F - Octopus

解题思路 对于每个宝藏维护个区间&#xff0c;答案一定在这些区间中对于每个区间的端点由小到大排序对于每个点进行判断&#xff0c;若当前位置合法&#xff0c;则该点一定为一个右端点则该点到前一个端点之间均为合法点若前一个点不合法&#xff0c;则一定是某一个区间限制的…

Vue3:使用Pinia存储、读取、修改数据

一、存储数据 Pinia插件中&#xff0c;存储数据的配置项是state count.ts import {defineStore} from piniaexport const useCountStore defineStore(count,{// 真正存储数据的地方state(){return {sum:6}} })loveTalk.ts import {defineStore} from piniaexport const use…

Xen Server 8 Install

Xen Sevrer 前言 XenServer&#xff08;以前称为 Citrix Hypervisor&#xff09;是业界领先的平台&#xff0c;实现了经济高效的桌面、服务器和云虚拟化基础结构。XenServer 支持任意规模或类型的组织整合计算资源&#xff0c;以及将计算资源转换为虚拟工作负载&#xff0c;从…