emmm,就出了一道简单的背包密码,Misc
那道图片差第三部分的flag
官方wp
,https://www.yuque.com/yuqueyonghu30d1fk/gd2y5h/yleeg03c0ucdoac6
Crypto
complex_enc
超递增背包问题
c = 287687761937146187597379915545639385740275457170939564210821293233370716878150576 key = [...] flag = '' for i in key[::-1 ]: if i <= c: flag += '1' c -= i else : flag += '0' flag = flag[::-1 ] for i in range (0 , len (flag), 8 ): print (chr (int (flag[i:i+8 ], 2 )), end='' )
1z_RSA
放个题目先
from Crypto.Util.number import *from sympy import *import osfrom secrets import flagnbit =130 e = 3 l = getPrime(505 ) m = bytes_to_long(flag + os.urandom(64 )) assert len (flag) == 29 while True : p, q = getPrime(nbit), getPrime(nbit) PQ = int (str (p<<120 )+str (q)) QP = int (str (q<<120 )+str (p)) if isPrime(PQ) and isPrime(QP): break n = PQ * QP PP = nextprime((PQ >> 190 ) * (QP & (2 ** 190 - 1 ))) QQ = nextprime((QP >> 190 ) * (PQ & (2 ** 190 - 1 ))) N = PP * QQ M = pow (m,1 ,l) c = pow (m,e,N) print ('n =' , n)print ('M =' , M)print ('l =' , l)print ('c =' , c)''' n = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691 M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322 l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189 c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923 '''
注意
PQ = int (str (p<<120 )+str (q)) QP = int (str (q<<120 )+str (p))
两个字符串相加,是拼接的,所以需要获取后面的p、q
的十进制的长度,测试到大概为一个39,另一个40
写成这样的表达
P Q = p ∗ 2 120 ∗ 1 0 39 + q PQ=p*2^{120}*10^{39}+q P Q = p ∗ 2 1 2 0 ∗ 1 0 3 9 + q
Q P = q ∗ 2 120 ∗ 1 0 40 + p QP=q*2^{120}*10^{40}+p Q P = q ∗ 2 1 2 0 ∗ 1 0 4 0 + p
n = P Q ∗ Q P = p ∗ q ∗ ( 2 240 ∗ 1 0 79 + 1 ) + ( p 2 + 10 ∗ q 2 ) ∗ 2 120 ∗ 1 0 39 n=PQ*QP=p*q*(2^{240}*10^{79}+1)+(p^{2}+10*q^{2})*2^{120}*10^{39} n = P Q ∗ Q P = p ∗ q ∗ ( 2 2 4 0 ∗ 1 0 7 9 + 1 ) + ( p 2 + 1 0 ∗ q 2 ) ∗ 2 1 2 0 ∗ 1 0 3 9
观察,可以把p*q
弄出来
n / / ( 2 240 ∗ 1 0 79 + 1 ) = p ∗ q + x n//(2^{240}*10^{79}+1)=p*q+x n / / ( 2 2 4 0 ∗ 1 0 7 9 + 1 ) = p ∗ q + x
n % ( 2 120 ∗ 1 0 39 ) ≡ p ∗ q m o d ( 2 120 ∗ 1 0 39 ) n \% (2^{120}*10^{39}) \equiv p*q\ mod(2^{120}*10^{39}) n % ( 2 1 2 0 ∗ 1 0 3 9 ) ≡ p ∗ q m o d ( 2 1 2 0 ∗ 1 0 3 9 )
注意的是
n % ( 2 120 ∗ 1 0 39 ) ≠ p ∗ q ,而是 p ∗ q m o d ( 2 120 ∗ 1 0 39 ) n \% (2^{120}*10^{39})\not ={p*q},而是p*q\ mod(2^{120}*10^{39}) n % ( 2 1 2 0 ∗ 1 0 3 9 ) = p ∗ q , 而 是 p ∗ q m o d ( 2 1 2 0 ∗ 1 0 3 9 )
所以
p ∗ q = k ∗ 2 120 ∗ 1 0 39 + n % ( 2 120 ∗ 1 0 39 ) p*q=k*2^{120}*10^{39}+n \% (2^{120}*10^{39}) p ∗ q = k ∗ 2 1 2 0 ∗ 1 0 3 9 + n % ( 2 1 2 0 ∗ 1 0 3 9 )
(话说官方那个高低位处理,我还真看不懂,emmmmm,不是太懂这个大数乘法)
然后p*q
无法直接分解,可以通过解方程分解
又发现e 与 ϕ 不互素 e与\phi 不互素 e 与 ϕ 不 互 素
可以转换为模QQ
下的m
最后通过CRT
求解
from Crypto.Util.number import *from sympy import *from functools import reducen = 18339446336492672809908730785358232636383625709800392830207979464962269419140428722248172110017576390002616004691759163126532392634394976712779777822451878822759056304050545622761060245812934467784888422790178920804822224673755691 M = 36208281423355218604990190624029584747447986456188203264389519699277658026754156377638444926063784368328407938562964768329134840563331354924365667733322 l = 56911058350450672322326236658556745353275014753768458552003425206272938093282425278193278997347671093622024933189270932102361261551908054703317369295189 c = 720286366572443009268610917990845759123049408295363966717060100862857351750759651979922104897091176824666482923148635058966589592286465060161271579501861264957611980854954664798904862706450723639237791023808177615189976108231923 e = 3 a = n % (2 **120 *10 **39 ) b = n//(2 **240 *10 **79 +1 ) for i in range (1000 ): for j in range (1000 ): if b-i == j*2 **120 *10 **39 +a: pq = b-i break print (pq)p, q = symbols('p q' ) res = solve([p*q-pq, (p*2 **120 *10 **39 +q)*(q*2 **120 *10 **40 +p)-n], [p, q]) p, q = res[1 ] PQ = int (str (p << 120 )+str (q)) QP = int (str (q << 120 )+str (p)) PP = nextprime((PQ >> 190 ) * (QP & (2 ** 190 - 1 ))) QQ = nextprime((QP >> 190 ) * (PQ & (2 ** 190 - 1 ))) N = PP*QQ def chinese_remainder (n, a ): sum = 0 prod = reduce(lambda a, b: a * b, n) for n_i, a_i in zip (n, a): p = prod // n_i sum += a_i * inverse(p, n_i) * p return int (sum % prod) print (GCD(e, PP-1 ))m_QQ = pow (c, inverse(e, QQ-1 ), QQ) print (long_to_bytes(m_QQ))print (long_to_bytes(chinese_remainder([l, QQ], [M, m_QQ])))
DASCTF{Ar3_Y0u_Su93_Abt139??}
Misc
png_master
就给了一张png
图片,010
打开,末尾
Q29uZ3JhdHVsYXRpb25zIG9uIGZpbmRpbmcgdGhlIGZpcnN0IHBhcmFncmFwaCBvZiBmbGFnLCBidXQgdGhlIHVuZGVyc3RhbmRpbmcgb2YgcG5nIGlzIGp1c3QgYmVnaW5uaW5nLgpmbGFnMTpEQVNDVEZ7MmZkOWU5ZmYtZTI3
Congratulations on finding the first paragraph of flag, but the understanding of png is just beginning. flag1:DASCTF{2fd9e9ff-e27
然后正常来说,lsb
应该会考察到,先看一下
观察到Alpha plane
7到0都存在异常
flag2:d-5405-c5f5-
利用zsteg
看看还有没有其他的信息
[?] 172 bytes of extra data after image end (IEND), offset = 0x3f2dd [?] 3394 bytes of extra data after zlib stream extradata:0 .. text: "Q29uZ3JhdHVsYXRpb25zIG9uIGZpbmRpbmcgdGhlIGZpcnN0IHBhcmFncmFwaCBvZiBmbGFnLCBidXQgdGhlIHVuZGVyc3RhbmRpbmcgb2YgcG5nIGlzIGp1c3QgYmVnaW5uaW5nLgpmbGFnMTpEQVNDVEZ7MmZkOWU5ZmYtZTI3" extradata:1 .. file: zlib compressed data
zsteg -E "extradata:1" flag.png > flag.zlib
得到的东西暂时没有用
应该是IDAT块隐写
使用pngcheck
查看png
图片的IDAT块
是否异常
└─$ pngcheck -v '/home/kali/桌面/flag.png' File: /home/kali/桌面/flag.png (258953 bytes) chunk IHDR at offset 0x0000c, length 13 2170 x 1080 image, 32-bit RGB+alpha, non-interlaced chunk IDAT at offset 0x00025, length 65536 zlib: deflated, 32K window, default compression chunk IDAT at offset 0x10031, length 65536 chunk IDAT at offset 0x2003d, length 65536 chunk IDAT at offset 0x30049, length 58674 chunk IDAT at offset 0x3e587, length 3394 chunk IEND at offset 0x3f2d5, length 0 additional data after IEND chunk ERRORS DETECTED in /home/kali/桌面/flag.png
上一个IDAT块数据还未填满就出现下一个,可以知道这段IDAT数据块有问题
保留第五个IDAT块(因为它是人为加进来的),将其他IDAT块都删除并保存,使用到的工具是tweakpng
按道理下一步是要爆破宽高的,但是它crc校验
的宽高是正确的,说明不是根据crc值
来确定的,不知道怎么搞了
有个自动crc
校验宽高工具https://github.com/AabyssZG/Deformed-Image-Restorer
隐写这里,参考了https://www.cnblogs.com/cierra/p/17357133.html
参考这位师傅的wp
https://mumuzi7179.github.io/docs/Blog/CTFWP/DASCTF2024暑期挑战赛#png_master
import zlibdef decompress_data (zip_file, new_file ): zip_file = open (zip_file, 'rb' ) new_file = open (new_file, 'wb' ) decompress = zlib.decompressobj() data = zip_file.read(1024 ) while data: new_file.write(decompress.decompress(data)) data = zip_file.read(1024 ) new_file.write(decompress.flush()) zip_file.close() new_file.close() a = "flag.zlib" b = "new_flag.zlib" decompress_data(a, b)
zlib
解压,得到size: 750500
然后根据开头的01 80 80 80 00……
猜测出这是RGB图像
?翻了挺久的资料了,还是没搞懂,但是也知道了这个
color_type字段的值对应于以下PNG颜色类型: 0: 灰度图像 2: 真彩色图像(RGB) 3: 索引彩色图像 4: 灰度图像+α 6: 真彩色图像+α(RGBA)
宽高的计算是这样的
最后
还是存在一些不明白之处的
Web
Sanic’s revenge()
源代码
from sanic import Sanicimport osfrom sanic.response import text, htmlimport sysimport randomimport pydashclass Pollute : def __init__ (self ): pass app = Sanic(__name__) app.static("/static/" , "./static/" ) @app.route("/*****secret********" ) async def secret (request ): secret='**************************' return text("can you find my route name ???" +secret) @app.route('/' , methods=['GET' , 'POST' ] ) async def index (request ): return html(open ('static/index.html' ).read()) @app.route("/pollute" , methods=['GET' , 'POST' ] ) async def POLLUTE (request ): key = request.json['key' ] value = request.json['value' ] if key and value and type (key) is str and 'parts' not in key and 'proc' not in str (value) and type (value) is not list : pollute = Pollute() pydash.set_(pollute, key, value) return text("success" ) else : log_dir = create_log_dir(6 ) log_dir_bak = log_dir + ".." log_file = "/tmp/" + log_dir + "/access.log" log_file_bak = "/tmp/" + log_dir_bak + "/access.log.bak" log = 'key: ' + str (key) + '|' + 'value: ' + str (value); os.system("mkdir /tmp/" + log_dir) with open (log_file, 'w' ) as f: f.write(log) os.system("mkdir /tmp/" + log_dir_bak) with open (log_file_bak, 'w' ) as f: f.write(log) return text("!!!此地禁止胡来,你的非法操作已经被记录!!!" ) if __name__ == '__main__' : app.run(host='0.0.0.0' )