您的位置:首页 > 汽车 > 时评 > 郑州制作网站_东莞seo公司_杭州seo公司_长尾关键词挖掘工具

郑州制作网站_东莞seo公司_杭州seo公司_长尾关键词挖掘工具

2024/12/24 3:55:14 来源:https://blog.csdn.net/Pisces50002/article/details/144492615  浏览:    关键词:郑州制作网站_东莞seo公司_杭州seo公司_长尾关键词挖掘工具
郑州制作网站_东莞seo公司_杭州seo公司_长尾关键词挖掘工具

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}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com