ByteCTF2024

wp参考:

2024 ByteCTF wp

2024 ByteCTF WP- Nepnep

ByteCTF 2024 writeup by Arr3stY0u

五冠王!ByteCTF 2024 初赛WriteUp By W&M

ByteCTF 2024 By W&M - W&M Team

ByteCTF Re WP - 吾爱破解 - 52pojie.cn

2024 ByteCTF - BediveRe_RE - 博客园 (cnblogs.com)

Rev

babyapk

DIE扫出来是一个flutter架构的apk,考虑用blutter来反编译

我之前在ubuntu上配置成功过,后来因为虚拟机坏了全删了。重新配置时kali、ubuntu

学习孤恒师傅在win上又装了一遍,参考下面的文章

[原创]《安卓逆向这档事》番外实战篇3-拨云见日之浅谈Flutter逆向-Android安全-看雪-安全社区|安全招聘|kanxue.com

出现上面的报错就是网络问题(全局代理)

cmake相关的报错就是缺少环境,一定要检查VS这个模块有没有安装

成功之后就快乐启动

得到输出

根据教程利用里面的文件可以恢复符号表,把addName的脚本跑一遍(我跑一遍之后符号表还是缺,结果又跑了一遍一样的脚本就好了,匪夷所思)

搜一下apk名字段可以找到一些相关的函数

babyapk_main__MyHomePageState::test_264c0c里藏着大量逻辑,不过需要修复一下函数结构。对识别成数据的部分,我们采取“先U再C再P”的原则,对代码反复调教,最终可以恢复出能看的伪代码

看到一些字符串匹配的函数名,猜测是对字符串开头的检测;35行45应该是字符串长度

我们用frida hook看看情况,一般的安卓模拟器跑不起来,没有arm的底层,推荐直接上真机

blutter提供了非常方便的hook脚本,只要改个地址就能hook

手机端启动frida-server

frida -U -f com.example.babyapk -l E:\Downloads\CTF\ByteCTF2024\babyapk_output\blutter_frida.js

注入后触发

可以看到是一个flag头检测

0x198d18的函数跑不出东西,0x198df8可以跑出上面的flag头

hook 264d88 则可以跑出flag尾部验证

所以flutter层只是个表面,对flag格式进行验证,加密部分还在rust部分

m3N4B5V6在librust_lib_babyapk.so里面有字符串

定位到这个函数里

这个函数里还有greet字段,wm的wp解释了这一点

sub_39B24里面翻,最终找到3AEE0看着像加密函数

这里的连接符验证,应该为flag的格式

最后的验证部分,一堆方程式,又是z3

from z3 import *
data = [0x1EE59, 0x22A, 0x1415, 0x40714, 0x13E0, 0x8B8, 0xFFFDCEA0, 0x313B,0x3D798, 0xFFFFFE6B, 0xC4E, 0x23884, 0x8D, 0x1DB4, 0xFFFC1328, 0x1EAC,0x43C64, 0x142B, 0xFFFFF622, 0x23941, 0xFFFFEF6D, 0x120C, 0xFFFBD30F,0x1EBE, 0x45158, 0xFFFFEF66, 0x1D3F, 0x4C46B, 0xFFFFF97A, 0x1BFD,0xFFFBA235, 0x1ED2
]
for i in range(4):s = Solver()v46, v47, v45, v44, v48, v49, v50, v51 = BitVecs("v46 v47 v45 v44 v48 v49 v50 v51", 8)s.add(And(48 <= v46, v46 <= 127))s.add(And(48 <= v47, v47 <= 127))s.add(And(48 <= v45, v45 <= 127))s.add(And(48 <= v44, v44 <= 127))s.add(And(48 <= v48, v48 <= 127))s.add(And(48 <= v49, v49 <= 127))s.add(And(48 <= v50, v50 <= 127))s.add(And(48 <= v51, v51 <= 127))s.add((v51 + v47 * v44 * v49 - (v46 + v50 + v45 * v48)) & 0xffffffff ==data[i * 8])s.add((v44 - v48 - v46 * v49 + v51 * v47 + v45 + v50) & 0xffffffff ==data[i * 8 + 1])s.add((v46 * v49 - (v48 + v51 * v47) + v45 + v50 * v44) & 0xffffffff ==data[i * 8 + 2])s.add((v47 + v48 * v46 - (v51 + v45) + v50 * v49 * v44) & 0xffffffff ==data[i * 8 + 3])s.add((v49 * v44 + v47 + v45 * v48 - (v50 + v51 * v46)) & 0xffffffff ==data[i * 8 + 4])s.add((v46 * v49 + v47 * v44 + v45 - (v50 + v48 * v51)) & 0xffffffff ==data[i * 8 + 5])s.add((v51 - v47 + v45 * v49 + v50 - v48 * v46 * v44) & 0xffffffff ==data[i * 8 + 6])s.add((v44 - v51 - (v47 + v49) + v48 * v46 + v50 * v45) & 0xffffffff ==data[i * 8 + 7])if s.check()==sat:print(s.model()[v46], end=",")print(s.model()[v47], end=",")print(s.model()[v45], end=",")print(s.model()[v44], end=",")print(s.model()[v48], end=",")print(s.model()[v49], end=",")print(s.model()[v50], end=",")print(s.model()[v51], end=",")
print()
byte = [51,50,101,55,53,48,99,56,102,98,50,49,52,53,54,50,97,102,50,50,57,55,51,102,98,53,49,55,54,98,57,99]
flag = ''
j = 0
for i in byte:flag += chr(i)
print(flag)

v45-v51八个变量,每个变量4字节,(4*8=32)+4(四个“-”)+9(“ByteCTF{}”)=45,可以推出四个连接符,但不知道加在哪儿

看了各个wp,可以通过经验猜测是GUID格式

GUID 的格式为“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,其中每个 x 是 0-9 或 a-f 范围内的一个十六进制数。例如:6F9619FF-8B86-D011-B42D-00C04FC964FF 即为有效的 GUID 值。

硬抠伪代码勉强能看出来一点,但是不太好看。不知有什么好方法


又研究了52的wp,感觉写的很好,提供了更多的思路

我们要充分利用blutter提供的资源

打开asm\babyapk\main.dart其实可以通过符号名猜测到很多逻辑

也是我们之前hook出来的数据

看到重要的m3N4B5V6函数,可以进行进一步定位

不过也没太多信息

不过IDA是能搜到simple的字符串的

顺着交叉引用就能找到加密函数位置

而且既然知道了加密函数,z3解完了不知道“-”加在哪里,也可以直接爆破其位置

#参考了rea1师傅的脚本!
from itertools import combinations# 原始字符串
original_string = "32e750c8fb214562af22973fb5176b9c"# 定义用于验证的 byte 数组(byte_18E46)
byte_18E46 = [ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,0x04, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
# 验证逻辑函数
def validate_hyphen_positions(input_str):byte = byte_18E46input_bytes = [ord(c) for c in input_str]# 模拟你提供的验证逻辑v2 = byte[input_bytes[0]]if v2 == 36:return Falsev3 = byte[input_bytes[v2]] + v2if v3 == 36:return Falsev4 = v3 + byte[input_bytes[v3]]if v4 == 36:return Falsev5 = v4 + byte[input_bytes[v4]]if v5 == 36:return Falsev6 = v5 + byte[input_bytes[v5]]if v6 == 36:return Falsev7 = v6 + byte[input_bytes[v6]]if v7 == 36:return Falsev8 = v7 + byte[input_bytes[v7]]if v8 == 36:return Falsev9 = v8 + byte[input_bytes[v8]]if v9 == 36:return Falsev10 = input_bytes[v9]if v10 != ord('-'):return Falsev12 = v9 + byte[input_bytes[v9]]if v12 == 36:return Falsev13 = v12 + byte[input_bytes[v12]]if v13 == 36:return Falsev14 = v13 + byte[input_bytes[v13]]if v14 == 36:return Falsev15 = v14 + byte[input_bytes[v14]]if v15 == 36:return Falsev16 = v15 + byte[input_bytes[v15]]if v16 == 36:return Falsev18 = input_bytes[v16]if v18 != ord('-'):return Falsev20 = v16 + byte[input_bytes[v16]]if v20 == 36:return Falsev21 = v20 + byte[input_bytes[v20]]if v21 == 36:return Falsev22 = v21 + byte[input_bytes[v21]]if v22 == 36:return Falsev23 = v22 + byte[input_bytes[v22]]if v23 == 36:return Falsev24 = v23 + byte[input_bytes[v23]]if v24 == 36:return Falsev25 = input_bytes[v24]if v25 != ord('-'):return Falsev27 = v24 + byte[input_bytes[v24]]if v27 == 36:return Falsev28 = v27 + byte[input_bytes[v27]]if v28 == 36:return Falsev29 = v28 + byte[input_bytes[v28]]if v29 == 36:return Falsev30 = v29 + byte[input_bytes[v29]]if v30 == 36:return Falsev31 = v30 + byte[input_bytes[v30]]if v31 == 36:return Falsev32 = input_bytes[v31]if v32 != ord('-'):return Falsereturn True# 生成插入 '-' 的位置的组合
positions = list(combinations(range(len(original_string) + 1), 4))  # 选择 4 个插入位置# 计数器
count = 0
valid_count = 0  # 成功验证的组合计数器# 遍历所有组合
for pos in positions:temp_str = original_string# 插入时要注意位置的偏移,每次插入后,字符串长度增加for i, p in enumerate(pos):temp_str = temp_str[:p + i] + '-' + temp_str[p + i:]  # 插入 '-' 并调整位置索引# 验证插入的 '-' 是否符合条件if validate_hyphen_positions(temp_str):print(f"Valid combination: {temp_str}")valid_count += 1  # 计数通过验证的组合# 计数count += 1# 打印总次数
print(f"Total combinations: {count}")
print(f"Total valid combinations: {valid_count}")
'''
Valid combination: 32e750c8-fb21-4562-af22-973fb5176b9c
Total combinations: 40920
Total valid combinations: 1
'''

ByteBuffer

010看到一堆点和边的字样,猜测是要画图

由于只给了个bin文件,没有太多的办法,只能对着结构硬猜,其实仔细观察是能发现一些端倪的

首先是Edge的部分

通过这几个字符的特征应该可以猜测,每个Edge #?字段的结构体数据应该是存在字符串前面的

用简单的脚本提取一下,可以发现,除了头尾的数据有点怪,中间部分的数据段都是很有规律的

结构体前部是一些很大的数字,01后面是两个四字节的整数,再往后是四字节的4,和四字节的9或者8

每个部分的含义看起来都不明所以,除了可以很勉强地看出最后一个数据段是字符串部分的长度

那先往下看一下dot的部分

结构也类似,不过既然是点,就可以猜测第2、3个四字节部分是x,y坐标。末尾的数据同上是字符串标识的长度

我们可以发现dot一共有120(0x78)个,而edge中这两个字段的值都不大于0x78

所以edge中这两个字段表示的是这条边两个端点的编号

至于前面的大数不知道什么意思,我们也不管了,上面那些数据足够我们画图

读取结构体数据的脚本如下,一些细节做了注释

# 参考了wm大佬的脚本,非常佩服wm的师傅!
import struct
import matplotlib.pyplot as pltdef u32(a):return struct.unpack('<I', a)[0] # 将一个字节序列解包为一个32位无符号整数(小端序)with open(R"E:\Downloads\CTF\ByteCTF2024\ByteBuffer\ByteBuffer.bin", 'rb') as fp:buffer = fp.read()begin_offset = 0x3ACaddr = begin_offset
edges = []
while addr <= 0x1203: #只读取Edge数据段倒数直到第二个结构体的内容#print(hex(addr))bts = bytes() # 创建空字节对象一枚id_length = u32(buffer[addr + 0x14:addr + 0x18]) #读取字符串长度部分#print(id_length)#不同的字符串长度 数据段末尾的空格长度都不一样if id_length == 9: #id段字符串长度为9时,数据末尾会空3个字节,其他的以此类推offset_in = 3elif id_length == 8:offset_in = 4elif id_length == 7:offset_in = 1bts += buffer[addr:addr + 0x14 + 4 + id_length + offset_in] #把一整段结构体保存为一个字节对象addr += 24 + id_length + offset_in #地址指针移动一个结构体的长度,到下一个结构体edges.append(bts)bts = buffer[addr + 12:addr + 44] #特殊处理最后一个结构体,因为它的长度和前面的不一样
edges.append(bts)
addr += 0x2C
'''
for i in edges:print(len(i),i)
'''
#print(hex(addr))dots = []
while addr <= 0x1f85: #读取到Dot数据段倒数第二个结构体#print(hex(addr))bts = bytes()bts += buffer[addr:addr + 16]id_length = u32(buffer[addr + 16:addr + 20])#print(id_length)if id_length == 8:offset_in = 4elif id_length == 7:offset_in = 1elif id_length == 6:offset_in = 2bts += buffer[addr + 0x10:addr + 0x10 + 4 + id_length + offset_in]addr += 0x14 + id_length + offset_indots.append(bts)
#print(hex(addr))bts = buffer[addr + 8:addr + 34] #最后一个结构体特殊处理
dots.append(bts)
'''
for i in dots:print(len(i),i)
'''
points = []
for i in dots:x_d = u32(i[4:8])y_d = u32(i[8:12]) points.append((x_d, y_d)) #读取dot数据中的坐标值id3 = u32(i[12:16]) #结构体后面部分,其实没啥用,因为看不懂什么意思#print(x_d, y_d, id3, i[-8:])points = points[:-2] + [points[-1], points[-2]] #读取的dot最后两个点数据弄反了,手动调整一下
#print(len(points))for i in edges:p1 = u32(i[8:12])p2 = u32(i[12:16])print(p1, p2, id3, i[-8:]) #读取edge数据中每条边两个端点的编号p2p = [120-p1, 120-p2] #points列表中的数据是倒着存进去的,检索索引值时索引值也是反的x_coords = [points[i][0] for i in p2p] # 检索x坐标y_coords = [points[i][1] for i in p2p] # 检索y坐标plt.plot(x_coords, y_coords, '-o') 
all_x_coords, all_y_coords = zip(*points)
plt.scatter(all_x_coords, all_y_coords) #绘制
plt.gca().invert_yaxis() #翻转y轴
plt.show()

ByteKit

给了这些玩意儿

sh文件是启动qemu镜像的脚本,qcow2是镜像

bios.bin大概是固件

qemu启动脚本,打开一个虚拟机,用root可以登陆

有个getflag.sh脚本

是一个flag验证,似乎目标是$BYTECTF_OUTPUT_VAR_FILE也就是"/sys/firmware/efi/efivars/ByteCTFOut-93e91ed6-1a7a-46a1-b880-c5c281700ea2"

binwalk看一下里面是有efi文件的,不过GUID不是我们想要的,先试试

从bios.bin中提取文件有两种方法

  1. 7zip直接解压

然后可以找到Bytekit字样的可疑文件

  1. 使用uefi_retool工具

python uefi_retool.py get-images bin路径

有ByteCTFIn、KEY:的字符串,不过函数部分被ollvm混淆了

D810可以大致去掉混淆

然后去看ModuleEntryPoint函数

有几个可疑的点

65行的第二个地址,是一长串十六进制,应该是一个文件

83行出现了11位循环异或

key的地址看起来有点怪

观察加密的文件

出现了微妙的对应,应该是异或的结果。所以得到异或的密钥实际上是这一部分(2CE83EE0BC1A0956B9D994)

这个位置之后都是填充的BD,没啥用。脚本把文件解密导出来

异或后头部也出现了MZ的PE头

#参考wm佬的
from idaapi import *
startaddr=0x3A37
xoraddr=0x3A2C
size=0x6c4 #实际上密钥前面那个数表示的就是文件大小
for i in range(size):patch_byte(startaddr+i,get_byte(startaddr+i)^get_byte(xoraddr+i%11))
fp=open("E:\Downloads\CTF\ByteCTF2024\ByteKit\output","wb+")
fp.write(get_bytes(startaddr,size))
fp.close()

导出的文件再次拖入IDA

一个开头“KEY:”的验证

下面是异或加密和验证flag

异或相当于流密钥加密,解密只要把加密过程再实现一遍即可

enc = [0x4B, 0x27, 0x42, 0x55, 0x48, 0x6E, 0x41, 0x29, 0x1F, 0x5E, 0x04, 0x04, 0x6B, 0x3E, 0x57, 0x5F, 0x08, 0x07, 0x5F, 0x3A, 0x31, 0x17, 0x40, 0x30, 0x5F, 0x7A, 0x75, 0x67, 0x36, 0x36, 0x36, 0x36]
key = [0x0000000000000062, 0x0000000000000001, 0x000000000000000B, 0x0000000000000079, 0x0000000000000002, 0x0000000000000003, 0x0000000000000074, 0x0000000000000003, 0x0000000000000007, 0x0000000000000065, 0x0000000000000004, 0x000000000000000E, 0x0000000000000064, 0x0000000000000005, 0x000000000000000D, 0x0000000000000061, 0x0000000000000006, 0x000000000000000A, 0x000000000000006E, 0x0000000000000007, 0x000000000000000F, 0x0000000000000063, 0x0000000000000008, 0x000000000000000C, 0x0000000000000065, 0x0000000000000009, 0x000000000000000A, 0x0000000000000000]for i in range(len(key)//3):v14 = key[i*3+1]v15 = v14 + key[i*3+2]while(v15 > v14):enc[v14] ^= key[i*3]v14 += 1flag = ''    
for i in enc:flag += chr(i)
print(flag)
# KEY:By71d@nnc6_Wan77_y@0_zug6666

输回去就可以得到flag,但是识别有点问题(前面是notepad里一起粘贴进来的,后面是手打./getflag.sh 然后从python复制的key粘贴的,后面的识别不出来,纯手打也识别不出来),不知为啥

Mobile

极限逃脱

直接分析IPA,选择里面的ByteCTFDemo部分

有不少符号表

看到ViewController firsButtonClicked

void __cdecl -[ViewController firsButtonClicked:](ViewController *self, SEL a2, id a3)
{uint32_t rand; // w20UITextField *v5; // x21NSString *v6; // x22void *input; // x23UIAlertController *v8; // x20UIAlertAction *v9; // x21UITextField *v10; // x22UILabel *v11; // x22UIButton *v12; // x19rand = arc4random_uniform(0x1F4u);v5 = objc_retainAutoreleasedReturnValue(-[ViewController firstInput](self, "firstInput"));v6 = objc_retainAutoreleasedReturnValue(-[UITextField text](v5, "text"));input = -[NSString integerValue](v6, "integerValue");objc_release(v6);objc_release(v5);if ( input == rand ){v8 = objc_retainAutoreleasedReturnValue(+[UIAlertController alertControllerWithTitle:message:preferredStyle:](&OBJC_CLASS___UIAlertController,"alertControllerWithTitle:message:preferredStyle:",CFSTR("提示"),CFSTR("恭喜你拿到入场券"),1LL));v9 = objc_retainAutoreleasedReturnValue(+[UIAlertAction actionWithTitle:style:handler:](&OBJC_CLASS___UIAlertAction,"actionWithTitle:style:handler:",CFSTR("确定"),0LL,&__block_literal_global_58));-[UIAlertController addAction:](v8, "addAction:", v9);-[ViewController presentViewController:animated:completion:](self,"presentViewController:animated:completion:",v8,1LL,0LL);v10 = objc_retainAutoreleasedReturnValue(-[ViewController inputText](self, "inputText"));-[UITextField setHidden:](v10, "setHidden:", 0LL);objc_release(v10);v11 = objc_retainAutoreleasedReturnValue(-[ViewController noticeLabel](self, "noticeLabel"));-[UILabel setHidden:](v11, "setHidden:", 0LL);objc_release(v11);v12 = objc_retainAutoreleasedReturnValue(-[ViewController secondButton](self, "secondButton"));-[UIButton setHidden:](v12, "setHidden:", 0LL);objc_release(v12);}else{v8 = objc_retainAutoreleasedReturnValue(+[UIAlertController alertControllerWithTitle:message:preferredStyle:](&OBJC_CLASS___UIAlertController,"alertControllerWithTitle:message:preferredStyle:",CFSTR("提示"),CFSTR("咒语错误"),1LL));v9 = objc_retainAutoreleasedReturnValue(+[UIAlertAction actionWithTitle:style:handler:](&OBJC_CLASS___UIAlertAction,"actionWithTitle:style:handler:",CFSTR("确定"),0LL,&__block_literal_global_53));-[UIAlertController addAction:](v8, "addAction:", v9);-[ViewController presentViewController:animated:completion:](self,"presentViewController:animated:completion:",v8,1LL,0LL);NSLog(&stru_10000C408.isa);}objc_release(v9);objc_release(v8);
}

是要过一个随机数啥的

再看看ViewController secondButtonClicked(推荐使用ida9,反编译效果好)

这里有个正则,暗示了flag格式也是uuid的

flag格式验证

初始化一些数据,很恶心的一点是第一部分的数据用的实际上是fifth的数据,first部分的数据根本没用

接下来是加密部分

先是用初始化的数据拼了一个flag格式的字符串,然后算了个SHA256

之后每个部分分段进行替换

    CC_SHA256(v14, v15, md);v16 = objc_retainAutoreleasedReturnValue(+[NSMutableString string](&OBJC_CLASS___NSMutableString, "string"));for ( i = 0LL; i != 32; ++i )objc_msgSend(v16, "appendFormat:", CFSTR("%02x"), md[i]);v18 = objc_retainAutoreleasedReturnValue(objc_msgSend(v16, "substringWithRange:", 1LL, objc_msgSend(f1, "length")));v19 = objc_retainAutoreleasedReturnValue(objc_msgSend(v18, "stringByReplacingOccurrencesOfString:withString:", CFSTR("a"), CFSTR("b")));objc_release(v18);v20 = objc_retainAutoreleasedReturnValue(objc_msgSend(v16, "substringWithRange:", objc_msgSend(f1, "length") + 1, objc_msgSend(f2_, "length")));v38 = objc_retainAutoreleasedReturnValue(objc_msgSend(v20, "stringByReplacingOccurrencesOfString:withString:", CFSTR("b"), CFSTR("c")));objc_release(v20);v21 = objc_retainAutoreleasedReturnValue(objc_msgSend(v16, "substringWithRange:", objc_msgSend(f2_, "length") + 1, objc_msgSend(f3, "length")));v43 = objc_retainAutoreleasedReturnValue(objc_msgSend(v21, "stringByReplacingOccurrencesOfString:withString:", CFSTR("c"), CFSTR("d")));objc_release(v21);v22 = objc_retainAutoreleasedReturnValue(objc_msgSend(v16, "substringWithRange:", objc_msgSend(f3, "length") + 1, objc_msgSend(f4, "length")));v42 = objc_retainAutoreleasedReturnValue(objc_msgSend(v22, "stringByReplacingOccurrencesOfString:withString:", CFSTR("d"), CFSTR("e")));objc_release(v22);v23 = objc_retainAutoreleasedReturnValue(objc_msgSend(v16, "substringWithRange:", objc_msgSend(f4, "length") + 1, objc_msgSend(f5, "length")));v24 = objc_retainAutoreleasedReturnValue(objc_msgSend(v23, "stringByReplacingOccurrencesOfString:withString:", CFSTR("e"), CFSTR("f")));objc_release(v23);v25 = objc_retainAutoreleasedReturnValue(-[NSArray objectAtIndexedSubscript:](v10, "objectAtIndexedSubscript:", 0LL));

6c9838a3c6810bdb2633ed5910b8547c09a7a4c08bf69ae3a95c5c37f9e8f57e

enc = 'a67be199da4b-b092-bd3e-e777-a67be199da4b'
hash = '6c9838a3c6810bdb2633ed5910b8547c09a7a4c08bf69ae3a95c5c37f9e8f57e'
p1 = ''
for i in range(1,9):p1 += hash[i]p1 = p1.replace('a', 'b')
print(p1)p2 = ''
for i in range(9,13):p2 += hash[i]p2 = p2.replace('b', 'c')
print(p2)p3 = ''
for i in range(5,9):p3 += hash[i]p3 = p3.replace('c', 'd')
print(p3)p4 = ''
for i in range(5,9):p4 += hash[i]p4 = p4.replace('d', 'e')
print(p4)p5 = ''
for i in range(5,17):p5 += hash[i]p5 = p5.replace('e', 'f')
print(p5)flag = 'ByteCTF{' + p1 + '-' + p2 + '-' + p3 + '-' + p4 + '-' + p5 + '}'
print(flag)
# ByteCTF{c9838b3c-6810-8a3d-8a3c-8a3c6810bdb2}

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

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

相关文章

C#,在 C# 语言中将 LaTeX 转换为 PNG 或 JPG 图像

在 C 语言中将 LaTeX 转换为 PNG 或 JPG 图像# 12月 28&#xff0c; 2021 2 分钟 法尔汉拉扎 在 C 语言中将 TeX 转换为 PNG JPG 图像# TeX 格式用于处理技术和科学文件。它通常用于交流或发布此类文档。在某些情况下&#xff0c;您可能需要将 TeX 文件渲染为 PNG 或 JPG 等图像…

AI监控赋能健身馆与游泳馆全方位守护,提升安全效率

一、AI视频监控技术的崛起 随着人工智能技术的不断发展&#xff0c;AI视频监控正成为各行业保障安全、提升效率的关键工具。相比传统监控系统&#xff0c;AI技术赋予监控系统实时分析、智能识别和精准预警的能力&#xff0c;让“被动监视”转变为“主动防控”。 二、AI监控应用…

搭建Tomcat(一)---SocketServerSocket

目录 引入1 引入2--socket 流程 Socket&#xff08;应用程序之间的通讯保障&#xff09; 网卡(计算机之间的通讯保障) 端口 端口号 实例 client端 解析 server端 解析 相关方法 问题1&#xff1a;ServerSocket和Socket有什么关系&#xff1f; ServerSocket Soc…

爬虫学习案例5

爬取b站一个视频 罗翔老师某一个视频很刑 单个完整代码&#xff1a; 安装依赖库 pip install lxml requests import osimport requests import re from lxml import etree import json # 格式化展开输出 from pprint import pprint # 导入进程模块 import subprocess head…

【深度学习】 零基础介绍卷积神经网络(CNN)

零基础介绍 卷积神经网络&#xff08;CNN&#xff0c;Convolutional Neural Network&#xff09;是深度学习中的一种神经网络&#xff0c;特别擅长处理图像和视频等有空间结构的数据。 假设我们在做一个“照片分类”的任务&#xff0c;比如判断一张照片中是猫还是狗。下面用一…

【计算机组成原理】实验二:通用寄存器单元实验

实验二&#xff1a;通用寄存器单元实验 一、实验目的 了解通用寄存器的组成和硬件电路&#xff0c;利用通用寄存器实现数据的置数、左移、右移等功能。 二、实验内容 数据输入通用寄存器 寄存器内容无进位位左移实验 寄存器内容无进位位右移实验 三、实验步骤和结果 实…

4G模块详解

在之前的教程中&#xff0c;无线通信技术我们学习了蓝牙和 WiFi&#xff0c;今天我们要来学习 4G。 4G 模块在距离上有个突破&#xff0c;它不像蓝牙短距离&#xff0c;也不像 WiFi 只能在局域网&#xff0c;4G 模块可使用户无论在哪&#xff0c;只要有 4G 网络信号覆盖&#…

Visual Studio 使用 GitHub Copilot 聊天

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

TimerPickerDialog组件的用法

文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了Snackbar Widget相关的内容,本章回中将介绍TimePickerDialog Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的TimePickerDialog是一种弹出窗口,只不过窗口的内容固定显示为时间,它主…

Linux高并发服务器开发 第四天(wc/whoami命令 权限修改chmod 添加/删除用户(组) 切换用户 修改文件所有者/所属组 查找/过滤)

目录 1.wc和whoami命令 1.1wc命令 1.2whoami命令 2.用户权限/用户/用户组 2.1修改文件权限chmod 2.1.1文字设定法 2.1.2数字设定法 2.2添加删除新用户和新用户组 2.3切换用户 2.4修改文件所有者和所属组 2.4.1修改所有者 2.4.2修改所属组 3.查找和过滤 3.1find—…

微服务架构导学

一. 什么是微服务 微服务是一个软件架构风格&#xff0c;将一个大型的项目拆分成多个小项目&#xff0c;每个项目都被称为一个微服务&#xff0c;通过多个微服务共同组成一个大的项目。 二. 单体架构和微服务架构 单体架构 将整个项目的功能、模块全部堆积在一个项目中 优点&am…

【kubernetes】kubectl get nodes报NotReady

目录 1. 说明2. 问题描述3. kube-flannel.yml 1. 说明 1.这里k8s的版本是v1.17.4。2.若kube-flannel.yml中的镜像拉取不下来&#xff0c;可以下载本文章的文件资源&#xff0c;手动docker load -i ***.tar的方式。3.v1.17.4的kube-flannel.yml参考下面代码。4.通过kubectl get…

web实操7——ServletContext

概念 和服务器通信 功能 解释说明&#xff1a; mime&#xff1a;互联网中一种文件的类型&#xff0c;可以用servletContext对象来获取。 域对象&#xff1a;用来共享数据&#xff0c;里面有一些get,set,removeAttribute,只要搞清楚ServletContext对象的域的范围是什么 如何…

LLMC:大语言模型压缩工具的开发实践

关注&#xff1a;青稞AI&#xff0c;学习最新AI技术 青稞Talk主页&#xff1a;qingkelab.github.io/talks 大模型的进步&#xff0c;正推动我们向通用人工智能迈进&#xff0c;然而庞大的计算和显存需求限制了其广泛应用。模型量化作为一种压缩技术&#xff0c;虽然可以用来加速…

舌头分割数据集labelme格式2557张1类别

数据集格式&#xff1a;labelme格式(不包含mask文件&#xff0c;仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数)&#xff1a;2557 标注数量(json文件个数)&#xff1a;2557 标注类别数&#xff1a;1 标注类别名称:["tongue"] 每个类别标注的框数&#xff1…

测试工程师八股文03|Python编程题

一、题目 1、合并两个数组 class Solution:def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:nums1[m:] nums2nums1.sort()2、判断链表中是否有环 class Solution:def hasCycle(self, head: ListNode) -> bool:seen set()while head:if…

MyBatis-Plus 基础

教程 视频教程&#xff1a;https://www.bilibili.com/video/BV1Xu411A7tL 详细文档&#xff1a;https://b11et3un53m.feishu.cn/wiki/PsyawI04ei2FQykqfcPcmd7Dnsc 常见注解 MybatisPlus就是根据PO实体的信息来推断出表的信息&#xff0c;从而生成SQL的。默认情况下&#xf…

VMware Workstation Pro 17 下载 以及 安装 Ubuntu 20.04.6 Ubuntu 启用 root 登录

1、个人免费版本 VMware Workstation Pro 17 下载链接怎么找&#xff1f;直接咕咕 VMware 找到如下链接。链接如下&#xff1a;Workstation 和 Fusion 对个人使用完全免费&#xff0c;企业许可转向订阅 - VMware 中文博客 点进去链接之后你会看到如下&#xff0c;注意安装之后仍…

深度学习——激活函数、损失函数、优化器

深度学习——激活函数、损失函数、优化器 1、激活函数1.1、一些常见的激活函数1.1.1、sigmoid1.1.2、softmax1.1.3、tanh1.1.4、ReLU1.1.5、Leaky ReLU1.1.6、PReLU1.1.7、GeLU1.1.8、ELU 1.2、激活函数的特点1.2.1、非线性1.2.2、几乎处处可微1.2.3、计算简单1.2.4、非饱和性1…

智慧政务数据中台建设及运营解决方案

数据中台&#xff1a;政府数字化转型的引擎 数据中台作为政府数字化转型的核心驱动力&#xff0c;起源于美军的作战体系&#xff0c;强调高效、灵活与强大。它不仅促进了政府决策的科学性&#xff0c;还推动了政府服务的精细化与智能化。 数据中台的应用场景&#xff1a;数字…