Misc 成功男人背后的女人 Challenge
每个成功的男人背后都站着一个伟大的女人。
Solution 用 TweakPNG 打开图片检查发现 mkBT 块,这是 Adobe 专属的数据块,要使用 fireworks 8 打开
隐藏掉上面的图层,只显示下面的图层
图片下方的符号,将 ♂ 映射为 1,♀ 映射为 0 得到:
1 010001000100000101010011010000110101010001000110011110110111011100110000011011010100010101001110010111110110001001100101011010000011000101101110010001000101111101001101010001010110111001111101
二进制转字符得到 flag
FLAG 1 DASCTF{w0mEN_beh1nD_MEn}
polar Challenge
给你8个擦除率为0.5的比特位传输4比特信息,你能使每个比特的成功传输概率超过50%吗?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import numpy as np, randomclass DefaultTransmission : def __init__ (self ): self .n_channels = 8 self .original_erasure_probability = 0.5 def simulate_bit_recovery (self, n_bits=4 , trials=100 ): """ 模拟 8 信道传输 n_bits 比特,每比特重复 trials 次 返回每个比特的成功恢复率 """ success = np.zeros((self .n_channels, n_bits)) for trial in range (trials): bits = np.random.randint(0 , 2 , size=n_bits) for ch in range (self .n_channels): for i, b in enumerate (bits): erased = (np.random.rand() < self .original_erasure_probability) received = None if erased else b if received == b: success[ch, i] += 1 avg_success = success / trials print ("\n每信道比特成功率矩阵 (行=信道, 列=比特索引):" ) for ch in range (self .n_channels): rates = " " .join(f"{avg_success[ch,i]:.3 f} " for i in range (n_bits)) print (f"信道 {ch+1 } : {rates} " ) bit_avg = np.mean(avg_success, axis=0 ) print ("\n每比特平均恢复率:" ) for i, r in enumerate (bit_avg): print (f"Bit {i} : {r:.3 f} " ) return avg_success
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import numpy as npdef transmit_BEC (x, eps ): y = np.array(x, dtype=object ) erasures = np.random.rand(len (x)) < eps y[erasures] = None return y def polar_bit_challenge (N=8 , K=4 , eps=0.5 , trials=100 , polar_funcs=None ): """ polar_funcs: dict, 必须包含 'construction', 'encode', 'decode' """ if polar_funcs is None : raise ValueError("必须传入 polar_funcs 字典" ) construction = polar_funcs['construction' ] encode = polar_funcs['encode' ] decode = polar_funcs['decode' ] info_idx, frozen_idx, _ = construction(N, K, eps) per_bit_success = np.zeros(K, dtype=int ) for _ in range (trials): u = np.zeros(N, dtype=int ) info_bits = np.random.randint(0 , 2 , K) u[info_idx] = info_bits x = encode(u, N) y = transmit_BEC(x, eps) u_hat = decode(y, frozen_idx) recovered = u_hat[info_idx] per_bit_success += (recovered == info_bits).astype(int ) per_bit_rate = per_bit_success / trials print ("\n=== 每个信息位恢复成功率 ===" ) for i, idx in enumerate (info_idx): print (f"信息位 {idx:2d} : 恢复率 = {per_bit_rate[i]:.3 f} " ) all_above_eps = np.all (per_bit_rate > eps) two_above_07 = np.sum (per_bit_rate > 0.7 ) >= 2 challenge_pass = all_above_eps and two_above_07 print ("\n=== 挑战条件 ===" ) print (f"所有比特恢复率 > {eps:.2 f} ? {'✅' if all_above_eps else '❌' } " ) print (f"至少两个比特恢复率 > 0.7 ? {'✅' if two_above_07 else '❌' } " ) print (f"挑战 {'成功' if challenge_pass else '失败' } " ) return per_bit_rate, challenge_pass
Solution 任务: 在 8 条二进制擦除信道(BEC,擦除概率 $$\varepsilon=0.5$$)上传输 4 个信息比特(即 ($$N=8, K=4, \varepsilon=0.5$$)),实现一个 polar 库(包含 construction、encode、decode 三个函数),使得每个信息位的恢复成功率都大于 0.5,并且至少两个信息位的恢复率达到或超过 0.7。
约束: 只能替换上传的 polar 库代码;沙箱环境禁止使用某些内建(例如 set、object 等),代码命名要求(先前测试中)避免下划线等。通道模型为独立擦除:每个物理位以概率 0.5 被擦除(变成 None)。
关键观察与解法思路:
在 BEC 上,若把同一信息比特独立重复发送 (r) 次,至少有一次未被擦除的概率为 $$ 1 - \varepsilon^{r}. $$ 代入 ($$\varepsilon=0.5$$),当 ($$r=2$$) 时成功概率为 $$ 1 - 0.5^{2} = 0.75. $$ 这个值既大于 0.5,也大于 0.7,所以满足题目要求。
给定 ($$N=8, K=4$$),恰好可以把 4 个信息位各重复 2 次(占满 8 个物理位)。这是一种简单、鲁棒且在本问题规模上最优的策略。
结论: 使用“每信息位重复两次”的编码与对应的解码(只要任一副本到达即恢复该比特)在理论上能通过挑战。
上传的三函数实现片段:
不依赖被禁用的内建(避免使用 set、object 等)。
返回值与服务器接口兼容:construction(N,K,eps) 返回 infoIdx, frozenIdx, reli;encode(u,N) 返回长度为 N 的数组;decode(y,frozenidx) 返回长度为 N 的估计向量(整数 0/1)。
对于擦除(None)情形,decode 选择第一个非 None 的副本;若两副本均被擦除,默认判为 0(概率为 ($$\varepsilon^{2}$$))。
下面给出最终可上传的三函数实现片段(可直接放入 polar.py 并保证 import numpy as np 存在):
先写一个脚本用于发送/接收并处理数据:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 from pwn import *context.log_level = 'WARN' HOST = "45.40.247.139" PORT = 31149 SOLUTION_FILE = "solution.py" io = remote(HOST, PORT) with open (SOLUTION_FILE, "r" , encoding="utf-8" ) as f: solution_code = f.read() io.recvuntil(b'> ' ) io.sendline(b'2' ) prompt_str = '结束输入:' io.recvuntil(prompt_str.encode('utf-8' )) io.send(solution_code.encode('utf-8' )) io.sendline(b'\nEND' ) response = io.recvall(timeout=10 ).decode('utf-8' , errors='ignore' ) print ("\n--- 服务器最终响应 ---" )print (response)print ("--------------------" )io.close()
编写解题脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 def construction (N, K, eps ): klocal = N // 2 infoIdx = np.arange(klocal) frozenIdx = np.arange(klocal, N) reli = np.zeros(N, dtype=float ) return infoIdx, frozenIdx, reli def encode (u, N ): klocal = N // 2 x = np.zeros(N, dtype=int ) for i in range (klocal): val = int (u[i]) x[i] = val x[i + klocal] = val return x def decode (y, frozenidx ): N = len (y) klocal = N // 2 uhat = np.zeros(N, dtype=int ) for i in range (klocal): v = y[i] if v is None : v2 = y[i + klocal] if v2 is None : recovered = 0 else : recovered = int (v2) else : recovered = int (v) uhat[i] = recovered for j in range (klocal, N): uhat[j] = 0 return uhat
数学可信度:
每个信息位重复两次、两次擦除独立的情况下成功率为 $$ 1 - \varepsilon^{2}. $$ 代入 ($$\varepsilon=0.5$$) 得到 ($$1 - 0.25 = 0.75$$)。因此:
每个比特恢复率 ($$=0.75>0.5$$),满足“全部>0.5”;
所有信息位都达到了 0.75,自然至少两个比特 ≥ 0.7。
该策略利用了简单而强力的独立重复冗余,适用于擦除通道且在资源($$N=8$$)刚好整除的情况下最直接最优。
输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 --- 服务器最终响应 --- ✅ 用户 polar 库已安全加载 === 每个信息位恢复成功率 === 信息位 0 : 恢复率 = 0.880 信息位 1 : 恢复率 = 0.910 信息位 2 : 恢复率 = 0.910 信息位 3 : 恢复率 = 0.910 === 挑战条件 === 所有比特恢复率 > 0.50 ? ✅ 至少两个比特恢复率 > 0.7 ? ✅ 挑战 成功 挑战成功,FLAG: DASCTF{94485289736729714789730949105504} 欢迎参加挑战! 请选择操作: 1. 默认传输 2. 上传自定义 polar 库 3. 退出 > --------------------
FLAG 1 DASCTF{94485289736729714789730949105504}
DS&Ai Mini-modelscope Challenge
This is Mini-modelscope, perhaps it has some issues. Note: signature is “serve”.
Solution 湾区杯原题,exp出自这篇wp:https://mp.weixin.qq.com/s/5HbnVnNCj0c2AsjDTT8oSg
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 import osimport zipfiletry : import tensorflow as tf except Exception as e: raise SystemExit("请先安装 TensorFlow: pip install tensorflow-cpu\n错误: " + str (e)) OUT_DIR = "model_saved" ZIP_PATH = "model.zip" if os.path.exists(OUT_DIR): import shutil shutil.rmtree(OUT_DIR) if os.path.exists(ZIP_PATH): os.remove(ZIP_PATH) @tf.function(input_signature=[tf.TensorSpec(shape=[None , 1 ], dtype=tf.float32 )] ) def serve_fn (x ): data = tf.io.read_file("/flag" ) batch_size = tf.shape(x)[0 ] data_vec = tf.repeat(tf.expand_dims(data, 0 ), repeats=batch_size) return {"prediction" : data_vec} @tf.function(input_signature=[tf.TensorSpec(shape=[None , 1 ], dtype=tf.float32 )] ) def noop_fn (x ): batch_size = tf.shape(x)[0 ] const = tf.constant("MODEL_OK" , dtype=tf.string) vec = tf.repeat(tf.expand_dims(const, 0 ), repeats=batch_size) return {"prediction" : vec} class ModelModule (tf.Module): @tf.function(input_signature=[tf.TensorSpec(shape=[None , 1 ], dtype=tf.float32 )] ) def __call__ (self, x ): return serve_fn(x) module = ModelModule() tf.saved_model.save(module, OUT_DIR, signatures={"serve" : serve_fn, "noop" : noop_fn}) with zipfile.ZipFile(ZIP_PATH, "w" , compression=zipfile.ZIP_DEFLATED) as zf: for root, dirs, files in os.walk(OUT_DIR): for fname in files: full = os.path.join(root, fname) arcname = os.path.relpath(full, OUT_DIR) zf.write(full, arcname) print ("SavedModel saved to:" , OUT_DIR)print ("Zipped to:" , ZIP_PATH)
把生成的文件夹压缩后上传即可
FLAG 1 DASCTF{36064477511992355432059500484677}