当前位置: 首页 > news >正文

正规建网站企业批量查询指数

正规建网站企业,批量查询指数,wordpress 培训主题,自己搭建小程序目录 CTF 密码学总结 题目类型总结#xff1a; 简单密码类型#xff1a; 复杂密码类型#xff1a; 文件相关类型#xff1a; 算法类总结#xff1a; 密码学脚本类总结#xff1a; 单独的密文类型#xff08;优先使用ciphey工具#xff09; 多层传统加密混合 简单密码类型 复杂密码类型 文件相关类型 算法类总结 密码学脚本类总结 单独的密文类型优先使用ciphey工具 多层传统加密混合 Bugku的密码学的入门题/.-摩斯密码、url编码、出人意料的flag 攻防世界之混合编码base64解密、unicode解密、ASCII转字符脚本、传统base64解密、ASCII解密 单层传统加密 Bugku crypto之聪明的小羊题目描述暗示、栅栏密码 攻防世界之转轮机加密转轮机加密、 攻防世界之告诉你个秘密16进制转字符、键盘密码 攻防世界之sherlock大小写字符提取密码 攻防世界之Decrypt-the-Messagepoem codes诗歌加密、 文件相关类型 攻防世界之你猜猜16进制转字符、传统base64解密、16进制文件流 攻防世界之banana-princessROT13加密、文件流加密 流量相关类型 攻防世界之工业协议分析216进制转字符、 加密逻辑平铺类型 传统密码加密逻辑平铺 2021年9月绿城杯CRYPTO的[warmup]加密算法暴力破解、仿射密码、下标对应解密 复杂加密类型 RSA直接给参数类型 攻防世界之cr3-what-is-this-encryptionRSA通用脚本解密 攻防世界之OldDriver低加密指数广播攻击 RSA明文密钥文件类型 攻防世界之best_rsa明文密钥文件提取参数、RSA共模攻击、CTF-RSA-tool脚本修改 攻防世界之RSA256 RSA脚本逻辑加密类型 2021年9月广州羊城杯CRYPTO的BigRsaRSA多层模n加密、CTF-RSA-tool脚本修改、RSA模不互素 2021年9月绿城杯CRYPTO的RSA-1CTF-RSA-tool脚本修改、RSA通用脚本解密 2021年9月绿城杯CRYPTO的RSA-2费马分解算法 2021年10月广东强网杯CRYPTO的RSA AND BASE?排列组合算法、下标对应解密 ECC椭圆曲线加密 攻防世界之easy_ECCECC加密 LFSR反馈移位寄存器类型 攻防世界之streamgame1CTF中的LFSR考点(一)、文件读取对齐的二进制 攻防世界之streamgame2CTF中的LFSR考点(一)、文件读取对齐的二进制 js类型加密 js逻辑平铺类型 攻防世界之flag_in_your_hand1:字符串中文含义暗示、冗余中锁定关键代码 python类型逻辑加密 pyc文件反编译 攻防世界之easychallenge源代码修改逻辑解密、 传统密码类型解析 凯撒密码(24个字母) 摩斯密码(只有01(无规则)或.-空格或/做分隔符) 云影密码(01248) 栅栏密码(分组数作密钥) 培根密码(大小写的ABab而且必须是5个一组不是5个就考虑摩斯密码): 与佛论禅编码要加上佛曰才能转换(BASE64类型转不了就ROT13一下) 转轮机加密 键盘密码 poem codes诗歌加密 URL编码规则 仿射密码 非传统密码类型解析 CTF中的LFSR考点(一) LFSR简介 CTF的LFSR题目示例 解密工具、脚本积累 Ciphey工具 CTF-RSA-tool工具 RSA前景知识 RSA脚本工具使用说明 多组n,e,c在解题时长这个样子 一组n,e,c的题目样式 不同情景下工具运行示例 RSA通用的简单脚本已知p、q、e、c值 ECC加密 ECC脚本积累(解出最后的公钥和私钥即可) CTF 密码学总结 出人意料的flag 指在题目中获取到了flag但是这个flag可能长得不像flag或者flag还要经过进一步的脑洞处理而不是常规的解密处理。 非预期行为 指解题中出现与预想结果不符合的一系列非预期行为这基本说明了在中间或前面存在其他自己还没分析的操作。 冗余中锁定关键代码 从后往前看就是确定比较关键对象从该对象开始排除其他无关变量一步步找出与该对象有关的其它变量最后串起找到的所有相关变量然后开始逆向分析。 题目类型总结 题目描述暗示 指题目给出的描述中有解题的大方向思路以及对解题过程中出现的一些疑惑点的解释。 字符串中文含义暗示 指解题中遇到带有中文暗示的字符串这通常是出题者给的提示抓住暗示重新梳理思路往往是正确的选择。 简单密码类型 摩斯密码 指解题中的密文涉及摩斯密码摩斯密码的特征是以.-或01组成的分隔符有空格或斜杠/。 url编码 指解题中的密文涉及url编码url编码的特征是使用 % 其后跟随两位的十六进制数来替换非 ASCII 字符。 传统base64解密 指题目中密文是涉及base64加密密文通常是4的倍数基本元素是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789/和补充的 unicode解密 指解题中密文涉及 unicode 解密unicode现在已知的特征是ASCII英文也是ASCII码转unicode码时是 # 前缀 2 个 16 进制数并用 ; 分隔。中文转unicode时是 \u 4 个 16 进制数中间没有间隔。 举例1234 -----#49;#50;#51;#52; 牛逼--------\u725b\u903c ASCII解密 指解题中密文涉及ASCII码需要转成字符。ASCII共128个可显示字符范围是0~127或0~7F。不同通常每个ASCII码的间隔依据出题者来定。 栅栏密码 指解题中密文涉及栅栏密码因为栅栏密码有传统的矩阵型和 W 型所以需要自己辨认。根据题目给的 key 分段来逐个尝试。 转轮机加密 指解题中密文涉及转轮机加密转轮机密文的特点是等长的分好组的乱序字母原理是转齿轮把一个字母换成另一个来拼成一句话所以会有多组密钥但是只有一组密文。 格式举例等长的分好组的字符串 ZWAXJGDLUBVIQHKYPNTCRMOSFE KPBELNACZDTRXMJQOYHGVSFUWI 键盘密码 指解题中密文涉及键盘密码加密键盘密码的特征是4~6个为一组在键盘上呈包围态势有明显的间隔。 16进制转字符 指解题中密文是由16进制基本元素组成的0~F或0~f直接16进制转字符即可。 大小写字符提取密码 指解题中题目给出的密文是一篇小说之类的其中的内容里面并没有flag所以内容含义没有意义。但是有一些字母的大小写形式与其他的不一样这些不一样的字母提取出来就是一种加密类型了。 举例提取大写字符命令 cat 1.txt | grep -o [A-Z] |tr -d \n grep -o 只显示匹配到的字符串tr -d 删除指定字符不删除换行符的话就很长的打竖显示。 ROT13加密 指解题中给出的密文是简单的数字或字母但是难以判断加密类型这时可以尝试用一下ROT13之类的字符移动来转换一下由于是同一层面的数字和字母所以通常可以装换出同层的具备传统密码特征的密文就可以继续解题了。 poem codes诗歌加密 指解题中密文涉及poem codes诗歌加密poem codes诗歌加密的特征是诗歌 -- 关键词原文 -- 参照顺序排列密文 -- 按诗歌关键词对原文映射取值。 仿射密码 指解题中密文涉及仿射密码仿射密码加密的特征是一种替换密码它是一个字母对一个字母的。字母系统中所有字母都藉一简单数学方程加密。 复杂密码类型 ECC加密 是一种建立公开密钥加密的算法基于椭圆曲线数学的椭圆曲线密码学。 CTF-RSA-tool脚本修改 指解题中RSA类型是CTF-RSA-tool工具中内嵌类型的一种变形无法直接用工具生成答案需要重CTF-RSA-tool中锁定对应的代码抽出来自己修改才行。 factor_N.py是对应的解密逻辑封装解出p、q。 RSAutils.py是对应的输出结果部分解决精度和字节串转为字符串问题。 RSA通用脚本解密 指简单的RSA题目中直接给出或求出p、q、e、c的值不需要再用N来大数分解所有参数都有了就可以直接运行RSA解密脚本解题了。 RSA多层模n加密 指解题中给了多个模且都是2048bit 4096bit等无法正面分解的数。需要使用欧几里得算法求取模之间的公约数也可以直接用p1 gmpy2.gcd(n1, n2) 这个系统提供的欧几里得封装函数。根据欧几里德算法算出的p之后再用n除以p即可求出q由此可以得到的参数有p、q、n、e再使用常规方法计算出d即可破解密文。 注意 这和RSA模不互素很像但是模不互素只用一个n加密另一个n是给你求公因子而已。 RSA模不互素 指解题中RSA类型给了多个模n且都是2048bit 4096bit等无法正面分解的数与RSA多层模n加密的区别就是模不互素只用一个n加密另一个n是给你求公因子而已。 低加密指数广播攻击 指解题中RSA类型给了多个n、c、e广播指我们需要将一份明文进行多份加密但是每份使用不同的密钥密钥中的模数n不同但指数e相同且很小我们只要拿到多份密文和对应的n就可以利用中国剩余定理进行解密。 明文密钥文件提取参数 指解题中题目给了RSA的明文和密钥文件可能是多个所以无法直接用CTF-RSA-tool解题CTF-RSA-tool好像只能输入一对明文密钥文件。 密钥文件和明文文件读取出对应数字的方法提取n、e都是用Crypto.PublicKey.RSA模块再抽取对应的n,c属性的。 提取加密密文c则是直接二进制读取文件后用Crypto.Util.number模块的bytes_to_long函数转二进制流为数字的。 RSA共模攻击 指解题中题目给了两个相同的n不同的e、c来加密密文。 文件相关类型 16进制文件流 指解题中给的密文或者附件中的内容是16进制的文件流这需要16进制转字符后再base64解码后才能发现是类似于抓包的文件流。所以最开始的16进制流就是文件流扔入winhex中保存为指定后缀即可。 文件流加密 指解题中题目给的文件扔入winhex工具中16进制显示的内容文件头等信息不符合题目给的后缀或不符合题目的文件类型描述。这时就要考虑是否在文件流层面上进行了加密处理通常是简单的移位处理。 文件读取对齐的二进制 指解题中需要从文件中读取二进制数二进制数有时是不能直接从文件中复制粘贴转换的因为有时候会有乱码显示。可以用前面积累的 base64 编码的代码写一串从文件中读取对齐的二进制的代码。 (在线转换都会省略最开头的0导致结果位数错误进而导致结果错误所以自己要注意) f open(5key,rb) #以二进制格式打开文件 content f.read() #读取的是\xhh类型的十六进制 key[{:08}.format(str(bin(i)).replace(0b,)) for i in content] #从base64编码汲取的经验二进制8位对齐。 print(.join(key)[:19]) 算法类总结 费马分解算法 指RSA题目类型中模n是4个p、q的混合乘积。 费马分解算法的特征就是n是4个数的乘积分解n之后我们会得到p、p1、q、q1四组隔开的排列组合但是我们的脚本可以把组合限定成p * q1 p1 * q,和p * q p1 * q这样。 然后通过欧几里得算法求公因子的封装函数gcd(pq1,pq) p、gcd(p1q,p1q) q 求出两组各一个数然后就可以求出φ(n)φ(p)⋅φ(p1)⋅φ(q)⋅φ(q1)(p−1)⋅(q−1)⋅(p1−1)⋅(q1−1)了。 排列组合算法 指解题中加密表单缺少了多个字母但是这个多个字母有多个组合因为无法确定是那个组合才能拼凑出正确的加密表单所以需要用排列组合算法全部穷举出来。 密码学脚本类总结 ASCII转字符脚本 指解题中遇到长串ASCII码形式需要转字符但是一个个转太麻烦又没有在线的长串ASCII码转字符网站。且给出的长串ASCII码的间隔依情况而定如/119/101/这时需要自己根据对应间隔写出批量转换脚本。 源代码修改逻辑解密 指解题中在有较完整源代码的情况下代码逻辑比较明朗且可以逆向。这时需要充分利用有源代码的优势来在源代码中修改处逆向逻辑不要自己从头到尾另写一份。 暴力破解 指解题中对每个密文在ASCII的32~127中逐个正向加密对比找到加密后与密文对应的字符后取chr(i)。 下标对应解密 指解题中遇到单表替换类型类似于仿射密码或base家族变形表单加密正向字母表中每个字母的值使用一个简单的数学函数映射到对应的值。 对于这种加密映射的单表替换型我们可以反着来把正向表单全部加密得出反向表单密文在反向表单中的下标等同与flag在正向表单的下标就是下标等价类似于base64表单替换。 单独的密文类型优先使用ciphey工具 多层传统加密混合 Bugku的密码学的入门题/.-摩斯密码、url编码、出人意料的flag 摩斯密码是以.-或01组成的分隔符有空格或斜杠/所以直接扔去摩斯密码在线解密即可。 网址https://www.bejson.com/enc/morse/ 答案差不多了却被%u7b和%u7d卡住了猜想是{ }的url编码{的url编码是%7B}的url编码是%7D 所以去掉u符号这里u符号应该是什么十六进制之类的我也不知道 直接得到flag FLAG{D3FCBF17F9399504} 结果全部要小写 flag{d3fcbf17f9399504} 攻防世界之混合编码base64解密、unicode解密、ASCII转字符脚本、传统base64解密、ASCII解密 下载附件打开发现两个等号和19azA~Z的典型base64编码型直接base64转换 转了一堆#出来根据以前的做题经验猜unicode或hex 一开始用了十六进制来转转了个四不像出来后来发现转错了unicode在线解码网址 http://www.jsons.cn/unicode/ 这三个数的看着像ASCII因为题目暗示混合编码直接转换看看ASCCII表对照法 ASCII转字符脚本法这里因为string.split切片后返回的是列表所以可以直接用索引获取。 import re r/119/101/108/99/111/109/101/116/111/97/116/116/97/99/107/97/110/100/100/101/102/101/110/99/101/119/111/114/108/100 rre.split(/,r) #print(r) flag for i in range(1,len(r)): flagchr(int(r[i])) print(flag) 单层传统加密 Bugku crypto之聪明的小羊题目描述暗示、栅栏密码 好的传统栅栏密码下面是我以前的笔记 所谓栅栏密码就是把要加密的明文分成N个一组然后把每组的第1个字连起来形成一段无规律的话。 不过栅栏密码本身有一个潜规则就是组成栅栏的字母一般不会太多。一般不超过30个也就是一、两句话 传统栅栏密码(矩阵行列密钥是行数) 假如有一个字符串123456789 取字符串长度的因数进行分组假如key3 1 2 3 \\分组情况每三个数字一组分为三组 4 5 6 7 8 9 然后每一组依次取一个数字组成一个新字符串147258369 \\加密完成的字符串 解题 试一般的栅栏密码,取5为矩阵行数,得到 cyperrocaegireeol} eahfocec gnbip不正确取5为矩阵列数,得到 cebgccfe en eohplprgecrayoii aoreg”,也不正确除了常规的栅栏密码,还有 由题目描述可知分两组 fa{fe13f590 lg6d46d0d0} 那么答案很明显了上一个下一个即可得flag flag{6fde4163df05d900} 攻防世界之转轮机加密转轮机加密、 下载附件 好了记住了以后这个内容格式的就是转轮机加密了 原理就是转齿轮把一个字母换成另一个直接上一个修改后的大佬脚本 rotor [ #这里是要输入的转轮机原始字符串 ZWAXJGDLUBVIQHKYPNTCRMOSFE, KPBELNACZDTRXMJQOYHGVSFUWI, BDMAIZVRNSJUWFHTEQGYXPLOCK, RPLNDVHGFCUKTEBSXQYIZMJWAO, IHFRLABEUOTSGJVDKCPMNZQWXY, AMKGHIWPNYCJBFZDRUSLOQXVET, GWTHSPYBXIZULVKMRAFDCEONJQ, NOZUTWDCVRJLXKISEFAPMYGHBQ, XPLTDSRFHENYVUBMCQWAOIKZGJ, UDNAJFBOWTGVRSCZQKELMXYIHP, MNBVCXZQWERTPOIUYALSKDJFHG, LVNCMXZPQOWEIURYTASBKJDFHG, JZQAWSXCDERFVBGTYHNUMKILOP ] cipher NFQKSEVOQOFNP #这是要输入转轮机密文 key [2,3,7,5,13,12,9,1,8,10,4,11,6] #这是要输入转轮机密钥 tmp_list[] for i in range(0, len(rotor)): tmp k key[i] - 1 for j in range(0, len(rotor[k])): if cipher[i] rotor[k][j]: if j 0: tmprotor[k] break else: tmprotor[k][j:] rotor[k][0:j] break tmp_list.append(tmp) # print(tmp_list) message_list [] for i in range(0, len(tmp_list[i])): tmp for j in range(0, len(tmp_list)): tmp tmp_list[j][i] message_list.append(tmp) print(message_list) def spread_list(lst): for item in lst: if isinstance(item,(list,tuple)): yield from spread_list(item) else: yield item pass if __name__ __main__: for i in spread_list(message_list): print(**25) print(i) #在多个输出中查找有语义的字符串即为flag内容 攻防世界之告诉你个秘密16进制转字符、键盘密码 下载附件是个.txt文件打开 虽然没有f但是看起来就是16进制的基本组成单位0~F既然是十六进制就不用先十六进制转字符串目前接触的也只有十六进制转字符串了 转完之后是大小写字母混合和数字虽然没有/但看起来也的确是base64的基本组成单位了base64解码一下 得出的东西是一个四不像查了很多资料大部分说是键盘围起来的密码而且就叫键盘密码。 (唯一的暗示可能就是空格吧附上别人的一句话 看到明⽬张胆的空格,再瞅⼀下键盘,发现是键盘密码,) r5yG lp9I BjM tFhB T6uh y7iJ QsZ bhM 最后flag就是这些字符在键盘中围起来的键但是要大写才能提交 TONGYUAN 攻防世界之sherlock大小写字符提取密码 下载附件是一个txt文档内容是一篇小说。一开始我以为flag藏在关键字里我还用百度翻译一个个看内容现在回想起来真的太傻了查了资料才发现字符中是有异或点的大写字母就是要提取出来分析的地方 参考了别人的命令写了自己的提取大写shell命令 cat 1.txt | grep -o [A-Z] |tr -d \n 其中 grep -o 只显示匹配到的字符串 tr -d 删除指定字符不删除换行符的话就很长的打竖显示。 结果 然后可以发现都是ZERO和ONE的单词不是二进制字符串就是摩斯密码可是摩斯密码要空格这里没有所以是二进制字符串。 然后就是自己写python脚本转换01率一开始用for语句卡了一下后来直接换while语句 key1ZEROONEZEROZEROZEROZEROONEZEROZEROONEZEROZEROONEZEROZEROONEZEROONEZEROONEZEROONEZEROZEROZEROONEZEROONEZEROZEROONEONEZEROONEZEROZEROZEROZEROONEONEZEROONEZEROONEZEROONEZEROZEROZEROONEZEROZEROZEROONEONEZEROZEROONEONEONEONEZEROONEONEZEROONEONEZEROONEZEROZEROZEROZEROZEROONEONEZEROZEROZEROONEZEROONEONEZEROZEROONEZEROZEROZEROZEROONEONEZEROZEROONEONEZEROONEZEROONEONEONEONEONEZEROZEROONEONEZEROZEROZEROONEZEROONEONEZEROONEONEONEZEROZEROONEZEROONEONEONEONEONEZEROONEONEONEZEROZEROZEROZEROZEROONEONEZEROONEONEZEROZEROZEROZEROONEONEZEROONEZEROZEROZEROZEROONEONEZEROZEROZEROONEZEROONEONEZEROONEONEONEZEROZEROONEZEROONEONEONEONEONEZEROZEROONEONEZEROONEZEROONEZEROZEROONEONEZEROZEROZEROONEZEROZEROONEONEZEROONEONEONEZEROZEROONEONEZEROZEROONEONEZEROONEONEONEONEONEZEROONE flag i0 while ilen(key1): if key1[i]Zand key1[i1]Eand key1[i2]Rand key1[i3]O: i4 flag0 else: flag1 i3 print(flag) 结果 攻防世界之Decrypt-the-Messagepoem codes诗歌加密、 下载附件是个.txt文件内容是诗歌下面是一行四不像的英文后来发现是加密后的密文 诗歌类的加密 一开始还以为是唐伯虎点秋香中句子开头组成实际内容结果发现不是。查了查资料是poem codes加密。 然后我也不知道诗歌中关键词在哪而且题目诗歌内容也太长了所以只能用github的脚本了 (单独复制poemcode.py是会报错的因为文件中有其他依靠) git clone git://github.com/abpolym/crypto-tools 用法(python2ctfpoem是诗歌ctfcip是加密密文) python2 poemcode.py examples/2/ctfpoem examples/2/ctfcip 结果在众多输出中找到通顺的句子其实后面我也不知道后面开头的单词合不合理英语太菜了~(哭 ~) 文件相关类型 攻防世界之你猜猜16进制转字符、传统base64解密、16进制文件流 下载附件是一个.txt文件打开数字和字母 504B03040A0001080000626D0A49F4B5091F1E0000001200000008000000666C61672E7478746C9F170D35D0A45826A03E161FB96870EDDFC7C89A11862F9199B4CD78E7504B01023F000A0001080000626D0A49F4B5091F1E00000012000000080024000000000000002000000000000000666C61672E7478740A0020000000000001001800AF150210CAF2D1015CAEAA05CAF2D1015CAEAA05CAF2D101504B050600000000010001005A000000440000000000 往base家族想字母只有A~Fbase16解码 嗯~好熟悉后来想起来是web题中bp抓过的数据查了资料发现是一个zip文件的16进制数据竟然这么短也能组成zip的数据也是开了眼界zip里面也可以看到有个flag.txt文件。 一开始还直接修改成.zip后缀真是太天真了这是把hex数据放入txt文件啊。 打开winhex64复制粘贴成zip文件即可 解密的时候发现需要密码也不是zip伪加密。嗯~查了资料上网下载了Ziperello来爆破密码密码组成只能一个个试了 拿到了密码123456解压得到flag 攻防世界之banana-princessROT13加密、文件流加密 下载附件是一个PDF文件打不开题目英文提示香蕉原则好吧并没有什么用。(^ ~ ^)用记事本打开看一下内容 看起来像是一个文件流 扔到winhex64中再看一下嗯~其实一开始我也看不出有什么不妥红框那里是查了资料说与正常PDF有不同。 正常PDF头 到这里我的思想就和别人不一样了别人是思考%CQS-1.5和%PDF-1.x的关系。而我的第一反应是%CQS-1.5是一个没学过的文件头。。。。。毕竟没学过的文件头大把所以才有这么菜的自己。(哭~) 然后要问一个字母和另一个字母的关系加密中能把一个字母加密后是另一个字母的目前学过的有培根ROT1324字母移动的凯撒密码。ROT13和凯撒是同一个类型所以这里看看移动了多少位发现都是移动了13位。那么这整个PDF文件的内容应该都是移动了13位才会有这种有规则数据和文件乱码数据的现象吧。 附上kali的字符移动13位的命令shell这里tr命令的应用也是学到了知识A-Za-z按顺序对应N-ZA-Mn-za-m这连着的正则表达式之间不用空格也不用分号无拘无束 cat 1.pdf | tr A-Za-z N-ZA-Mn-za-m 2.pdf 然后转出来的PDF还自带黑格隐藏一开始我都不记得怎么分离了后来查资料说转html可以分离因为这是两张图片重叠在一起而已。事实上用我的嗨格式永久VIP会员PDF转HTML、WORD、PPT都是可以分离的。 流量相关类型 攻防世界之工业协议分析216进制转字符、 下载附件是一个pcapng流量文件 题目描述说已提取出上位机通信流量尝试分析出异常点获取FLAG。 flag形式为 flag{}这其实就是一个暗示flag就在通信流量中至于哪里异常查了资料有的说UDP的长度有部分异常要一个个点击查看。可是为什么我感觉UDP大的一堆小的也一堆也不知道哪里异常 然后就是题目暗示说flag在异常流量中那直接明文匹配查找不就行了先搜索flag无果换十六进制666c6167试试查到了用as printable text 选项dump下来即可 结果 加密逻辑平铺类型 传统密码加密逻辑平铺 2021年9月绿城杯CRYPTO的[warmup]加密算法暴力破解、仿射密码、下标对应解密 下载附件是一个文本文件逻辑代码平铺在里面 打开文件发现是一个简单的加密表单元素下标对应加密 因为下标加密是求余运算加密所以上网找了一下求余运算的逆运算结果发现负数的求余运算我解决不了。。。(哭~) 所以直接爆破算了这是我第一次真正用爆破做题所以比较生疏先回顾一下一开始我犯的错误。 一开始我写的脚本是这样的在ASCII的32~127中找到加密后与密文对应的字符然后取chr(i)然后错误就比较明显了因为for循环会一直向前走如果密文不按顺序摆放就会跳过所以没法用flagchr(i)的方法来获取密文结果就是得到明文字符----密文字符的对应然后要自己一个个拼接 mi_wen aoxL{XaaHKP_tHgwpc_hN_ToXnnht} str1 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #长度52 c0 flag[] cipher_text for i in range(32,127,1): if chr(i) in str1: #flag在a~Z内就获取下标并进行下标替换操作替换后还是在str1内啊 addr str1.find(chr(i)) cipher_text str1[(37*addr23) % 52] #求余52 else: #flag不在a~Z内加1后还是不在str1内 cipher_text chr(i) #flag在a~Z内就不用加密直接用 for a in mi_wen: if cipher_texta: print(a,chr(i)) 后来想了想竟然for循环一直往前走但是如果我换一下顺序每个密文字符遍历一次ASCII字符那不就密文也往前走了吗虽然这样的算法复杂度大大增加但是对电脑来说根本不值得一提好吧 mi_wen aoxL{XaaHKP_tHgwpc_hN_ToXnnht} str1 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #长度52 c0 flag[] cipher_text for a in mi_wen: for i in range(32,127): if chr(i) in str1: #flag在a~Z内就获取下标并进行下标替换操作替换后还是在str1内啊 addr str1.find(chr(i)) cipher_text str1[(37*addr23) % 52] #求余52 else: #flag不在a~Z内加1后还是不在str1内 cipher_text chr(i) #flag在a~Z内就不用加密直接用 if cipher_texta: flagchr(i) print(.join(flag)) 这里补充一些别人的做法他直接把码表加密之后按位找。是一种比较新颖的方法是对正向反向下标搞操作值得研究我感觉他的逻辑应该是这样的 还来有一天发现了是仿射密码 下标逆向脚本 mi_wen aoxL{XaaHKP_tHgwpc_hN_ToXnnht} str1 abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ #长度52 flag def encode(plain_text, a, b, m): cipher_text for i in plain_text: if i in str1: addr str1.find(i) cipher_text str1[(a*addrb) % m] else: cipher_text i return cipher_text reverseencode(str1,37,23,52) #正向表单全部加密得出反向表单 for i in mi_wen: #对应密文下标 if i in str1: addrreverse.find(i) #对应反向str1下标密文在反向表单中的下标等同与flag在正向表单的下标就是下标等价类似于base64表单替换。 flagstr1[addr] #获取正向明文因为小标是一样对应的 else: flagi print(flag) 结果 最后还差原本的负数求余逆运算了这个暂时找不到资料先放着。~ 复杂加密类型 RSA直接给参数类型 攻防世界之cr3-what-is-this-encryptionRSA通用脚本解密 没有附件依稀看得出有q、p、e、c是简单的RSA题目用我之前积累的RSA脚本CTF-RSA-tool跑一下。。。跑不出来(反复试了好多次还是报错我放弃了) 然后在网上查资料中找到一个讲得比较好的脚本和讲解 https://www.cnblogs.com/zhengna/p/13501563.html RSA的密钥对生成算法 讲得很透彻了解密的算法也提供了附上脚本和我的一点点见解这是RSA通用脚本 import libnum from Crypto.Util.number import long_to_bytes q int( 0xa6055ec186de51800ddd6fcbf0192384ff42d707a55f57af4fcfb0d1dc7bd97055e8275cd4b78ec63c5d592f567c66393a061324aa2e6a8d8fc2a910cbee1ed9, 16) p int( 0xfa0f9463ea0a93b929c099320d31c277e0b0dbc65b189ed76124f5a1218f5d91fd0102a4c8de11f28be5e4d0ae91ab319f4537e97ed74bc663e972a4a9119307, 16) e int( 0x6d1fdab4ce3217b3fc32c9ed480a31d067fd57d93a9ab52b472dc393ab7852fbcb11abbebfd6aaae8032db1316dc22d3f7c3d631e24df13ef23d3b381a1c3e04abcc745d402ee3a031ac2718fae63b240837b4f657f29ca4702da9af22a3a019d68904a969ddb01bcf941df70af042f4fae5cbeb9c2151b324f387e525094c41, 16) c 0x7fe1a4f743675d1987d25d38111fae0f78bbea6852cba5beda47db76d119a3efe24cb04b9449f53becd43b0b46e269826a983f832abb53b7a7e24a43ad15378344ed5c20f51e268186d24c76050c1e73647523bd5f91d9b6ad3e86bbf9126588b1dee21e6997372e36c3e74284734748891829665086e0dc523ed23c386bb520 n q * p d libnum.invmod(e, (p - 1) * (q - 1)) #invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)(p-1)(q-1)对ψ(n)保密,也就是对应根据ed1modψ(n),求出d m pow(c, d, n) # pow(x, y[, z])--函数是计算 x 的 y 次方如果 z 在存在则再对结果进行取模其结果等效于 pow(x,y) %z对应前面解密算法中MD(C)C^d(mod n) #print(m) #明文的十进制格式 string long_to_bytes(m) # m明文用长字节划范围 print(string.decode()) 攻防世界之OldDriver低加密指数广播攻击 下载附件一个.txt文件打开发现是c、n、e的RSA类型题 上网查了查发现类型是低加密指数广播攻击这里附上别人的话(里面的中国剩余定理我还没看懂) 首先介绍什么是广播加入我们需要将一份明文进行多份加密但是每份使用不同的密钥密钥中的模数n不同但指数e相同且很小我们只要拿到多份密文和对应的n就可以利用中国剩余定理进行解密。关于中国剩余定理请参考文章 https://www.cnblogs.com/freinds/p/6388992.html 只要满足以下情况我们便可以考虑使用低加密指数广播攻击 加密指数e非常小 一份明文使用不同的模数n相同的加密指数e进行多次加密 可以拿到每一份加密后的密文和对应的模数n、加密指数e 本来想参考着写一个脚本的发现CTF-RSA-tool工具里面好像可以解决低加密指数广播攻击。附上我以前的笔记 那么把题目的enc.txt照着格式摆放然后运行脚本即可 c : 7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042 e : 10 n : 25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803 c : 21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461 e : 10 n : 23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193 c : 6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983 e : 10 n : 18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623 c : 4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052 e : 10 n : 23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723 c : 22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672 e : 10 n : 31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493 c : 17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087 e : 10 n : 22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949 c : 1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639 e : 10 n : 25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043 c : 15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352 e : 10 n : 32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047 c : 8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797 e : 10 n : 52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553 c : 13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247 e : 10 n : 30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621 结果 积累一下别人的脚本以备后用(python3) import libnum import gmpy2 dic [{c:7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042, e: 10, n:25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803}, {c:21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461, e: 10, n:23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193}, {c:6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983, e: 10, n:18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623}, {c:4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052, e: 10, n:23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723}, {c:22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672, e: 10, n:31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493}, {c:17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087, e: 10, n:22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949}, {c:1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639, e: 10, n:25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043}, {c:15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352, e: 10, n:32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047}, {c:8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797, e: 10, n:52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553}, {c:13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247, e: 10, n:30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621}] n [] C [] for i in dic: n.append(i[n]) C.append(i[c]) N 1 for i in n: N * i Ni [] for i in n: Ni.append(N // i) T [] for i in range(10): T.append(int(gmpy2.invert(Ni[i], n[i]))) X 0 for i in range(10): X C[i] * Ni[i] * T[i] m10 X % N m gmpy2.iroot(m10, 10) print (libnum.n2s(m[0])) python2 import libnum import gmpy2 dic [{c:7366067574741171461722065133242916080495505913663250330082747465383676893970411476550748394841437418105312353971095003424322679616940371123028982189502042, e: 10, n:25162507052339714421839688873734596177751124036723831003300959761137811490715205742941738406548150240861779301784133652165908227917415483137585388986274803}, {c:21962825323300469151795920289886886562790942771546858500842179806566435767103803978885148772139305484319688249368999503784441507383476095946258011317951461, e: 10, n:23976859589904419798320812097681858652325473791891232710431997202897819580634937070900625213218095330766877190212418023297341732808839488308551126409983193}, {c:6569689420274066957835983390583585286570087619048110141187700584193792695235405077811544355169290382357149374107076406086154103351897890793598997687053983, e: 10, n:18503782836858540043974558035601654610948915505645219820150251062305120148745545906567548650191832090823482852604346478335353784501076761922605361848703623}, {c:4508246168044513518452493882713536390636741541551805821790338973797615971271867248584379813114125478195284692695928668946553625483179633266057122967547052, e: 10, n:23383087478545512218713157932934746110721706819077423418060220083657713428503582801909807142802647367994289775015595100541168367083097506193809451365010723}, {c:22966105670291282335588843018244161552764486373117942865966904076191122337435542553276743938817686729554714315494818922753880198945897222422137268427611672, e: 10, n:31775649089861428671057909076144152870796722528112580479442073365053916012507273433028451755436987054722496057749731758475958301164082755003195632005308493}, {c:17963313063405045742968136916219838352135561785389534381262979264585397896844470879023686508540355160998533122970239261072020689217153126649390825646712087, e: 10, n:22246342022943432820696190444155665289928378653841172632283227888174495402248633061010615572642126584591103750338919213945646074833823905521643025879053949}, {c:1652417534709029450380570653973705320986117679597563873022683140800507482560482948310131540948227797045505390333146191586749269249548168247316404074014639, e: 10, n:25395461142670631268156106136028325744393358436617528677967249347353524924655001151849544022201772500033280822372661344352607434738696051779095736547813043}, {c:15585771734488351039456631394040497759568679429510619219766191780807675361741859290490732451112648776648126779759368428205194684721516497026290981786239352, e: 10, n:32056508892744184901289413287728039891303832311548608141088227876326753674154124775132776928481935378184756756785107540781632570295330486738268173167809047}, {c:8965123421637694050044216844523379163347478029124815032832813225050732558524239660648746284884140746788823681886010577342254841014594570067467905682359797, e: 10, n:52849766269541827474228189428820648574162539595985395992261649809907435742263020551050064268890333392877173572811691599841253150460219986817964461970736553}, {c:13560945756543023008529388108446940847137853038437095244573035888531288577370829065666320069397898394848484847030321018915638381833935580958342719988978247, e: 10, n:30415984800307578932946399987559088968355638354344823359397204419191241802721772499486615661699080998502439901585573950889047918537906687840725005496238621}] n [] C [] for i in dic: n.append(i[n]) C.append(i[c]) N 1 for i in n: N * i Ni [] for i in n: Ni.append(N / i) T [] for i in xrange(10): T.append(long(gmpy2.invert(Ni[i], n[i]))) X 0 for i in xrange(10): X C[i] * Ni[i] * T[i] m10 X % N m gmpy2.iroot(m10, 10) print libnum.n2s(m[0]) 脚本解析 RSA明文密钥文件类型 攻防世界之best_rsa明文密钥文件提取参数、RSA共模攻击、CTF-RSA-tool脚本修改 下载题目是一个明文和密钥的4个附件 其实一开始我并不知道RSA的明文和密钥是怎么生成的CTF-RSA-tool中应对的也只有一对明文密钥文件而已,这里两对的话就只能查资料弄懂原理了再做了。 从别人的博客 攻防世界 best_rsa - vict0r - 博客园 中找到了从密钥文件和明文文件读取出对应数字的方法提取n、e都是用Crypto.PublicKey.RSA模块再抽取对应的n,c属性的。 提取加密密文c则是直接二进制读取文件后用Crypto.Util.number模块的bytes_to_long函数转二进制流为数字的。 from Crypto.PublicKey import RSA from Crypto.Util.number import * f1 open(publickey1.pem,rb).read() f2 open(publickey2.pem,rb).read() c1 open(cipher1.txt,rb).read() c2 open(cipher2.txt,rb).read() pub1 RSA.importKey(f1) pub2 RSA.importKey(f2) n1 pub1.n e1 pub1.e n2 pub2.n e2 pub2.e c1 bytes_to_long(c1) c2 bytes_to_long(c2) print(n1 ,n1) print(e1 ,e1) print(c1 ,c1) print(n2 ,n2) print(e2 ,e2) print(c2 ,c2) 结果 n1 13060424286033164731705267935214411273739909173486948413518022752305313862238166593214772698793487761875251030423516993519714215306808677724104692474199215119387725741906071553437840256786220484582884693286140537492541093086953005486704542435188521724013251087887351409946184501295224744819621937322469140771245380081663560150133162692174498642474588168444167533621259824640599530052827878558481036155222733986179487577693360697390152370901746112653758338456083440878726007229307830037808681050302990411238666727608253452573696904083133866093791985565118032742893247076947480766837941319251901579605233916076425572961 e1 117 c1 12847007370626420814721007824489512747227554004777043129889885590168327306344216253180822558098466760014640870748287016523828261890262210883613336704768182861075014368378609414255982179769686582365219477657474948548886794807999952780840981021935733984348055642003116386939014004620914273840048061796063413641936754525374790951194617245627213219302958968018227701794987747717299752986500496848787979475798026065928167197152995841747840050028417539459383280735124229789952859434480746623573241061465550303008478730140898740745999035563599134667708753457211761969806278000126462918788457707098665612496454640616155477050 n2 13060424286033164731705267935214411273739909173486948413518022752305313862238166593214772698793487761875251030423516993519714215306808677724104692474199215119387725741906071553437840256786220484582884693286140537492541093086953005486704542435188521724013251087887351409946184501295224744819621937322469140771245380081663560150133162692174498642474588168444167533621259824640599530052827878558481036155222733986179487577693360697390152370901746112653758338456083440878726007229307830037808681050302990411238666727608253452573696904083133866093791985565118032742893247076947480766837941319251901579605233916076425572961 e2 65537 c2 6830857661703156598973433617055045803277004274287300997634648800448233655756498070693597839856021431269237565020303935757530559600152306154376778437832503465744084633164767864997303080852153757211172394903940863225981142502888126928982009493972076013486758460894416710122811249903322437742241269681934551237431668187006176418124934488775505816544733929241927900392924886649420943699356314278255683484998359663404611236056664149725644051300950988495549164517140159041907329062655574220869612072289849679613024196448446224406889484578310512232665571188351621585528255501546941332782446448144033997067917984719103068519 这里两个相同的n就是共模攻击了在CTF-RSA-tool工具里有对公模攻击的解法 所以摆好格式后直接跑脚本 当然完全依靠工具是不行的所以抽取出CTF-RSA-tool对应代码做成脚本 (注意这里因为用python2运行所以不能用直接用open().read()来读取文档内容会报错。在外面要裹上libnum.s2n()才行) from Crypto.PublicKey import RSA from Crypto.Util.number import * import gmpy2 import libnum def share_N(N, e1, e2, c1, c2): gcd, s, t gmpy2.gcdext(e1, e2) if s 0: s -s c1 gmpy2.invert(c1, N) if t 0: t -t c2 gmpy2.invert(c2, N) plain gmpy2.powmod(c1, s, N) * gmpy2.powmod(c2, t, N) % N print(libnum.n2s(plain)) #上面的函数是从CTF-RSA-tool工具中抽取出来的下面的n、e、c属性是前面自己写的 c1libnum.s2n(open(cipher1.txt,rb).read()) c2libnum.s2n(open(cipher2.txt,rb).read()) pub1RSA.importKey(open(publickey1.pem).read()) pub2RSA.importKey(open(publickey2.pem).read()) n pub1.n e1 pub1.e e2 pub2.e share_N(n,e1,e2,c1,c2) 攻防世界之RSA256 下载压缩包解压是两个附件一个没有后缀一个.txt文件打开查看内容感觉是RSA的密文密钥文件 翻一下以前的笔记这是对CTF-RSA-tool使用的示例感觉题目类型就是这种密钥和密文的文件 验证猜想直接脚本跑一下得到flag RSA脚本逻辑加密类型 2021年9月广州羊城杯CRYPTO的BigRsaRSA多层模n加密、CTF-RSA-tool脚本修改、RSA模不互素 下载附件pub.py 打开文件发现内容是RSA加密过程 from Crypto.Util.number import * from flag import * n1 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061 n2 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073 e 65537 m bytes_to_long(flag) c pow(m, e, n1) c pow(c, e, n2) print(c %d % c) # output # c 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264 首先回顾一下以前的积累的RSA脚本解题的知识 然后回到羊城杯的题目你就会发现题目先用公共模数n1对flag m加密一次再用公共模数n2对RSA一次加密后的密文再加密一次这是两层加密 按理来说两层常规的RSA解密即可关键就是这里的n1、n2太大了无法硬分解常规的分解素数网站没法用。 然后就去查资料了因为RSA自己也不在行下面是从 CTF密码学中RSA学习以及总结_韦全敏的博客-CSDN博客 中找到的。 RSA小指数e攻击 如果RSA系统的公钥e选取较小的值可以使得加密和验证签名的速度有所提高但是如果e的选取太小就容易受到攻击。 有三个分别使用不同的模数n1,n2,n3但是都选取e3加密同一个明文可以得到 c1 pow(m,3,n1) c2 pow(m,3,n2) c3 pow(m,3,n3) 一般情况下n1,n2,n3互素否则会比较容易求出公因子从而安全性大幅度的减低。 利用公约数 如果两次加密的n1和n2具有相同的素因子可以利用欧几里德算法直接分解n1和n2. 通过欧几里德算法计算出两个n的最大公约数p def gcd(a, b): if a b: a, b b, a while b ! 0: temp a % b a b b temp def gcd_digui(a, b): if b ! 0: return a return gcd(b,a%b) p gcd(n1,n2) RSA小指数e攻击题目特征识别 识别此类题目通常会发现题目给了若干个n均不相同并且都是2048bit4096bit级别无法正面硬杠并且明文都没什么联系e也一般取65537。 根据欧几里德算法算出的p之后再用n除以p即可求出q由此可以得到的参数有p、q、n、e再使用常规方法计算出d即可破解密文。 和题目八九不离十那这道bigrsa就是这样解的了用两个公共模数n来求公因子 在此之前中间还有个小插曲那就是CTF-RSA-tool工具一开始我以为这中两个n、一个e、一个c的是CTF-RSA-tool工具中example的模不互素(下面是我以前的笔记) 后来怎么跑都跑不出来看了工具内对应代码才发现模不互素是给你两个单独分解不了的大数级n方便让你求公因子。然后只用一个n来加密对只用一个n。(我也是现在才理解模不互素的内容) 前面博客的欧几里德算法脚本不太会用所以直接抽出CTF-RSA-tool工具的这段脚本来用算了因为上面的求公因子代码已经写好了只要再加多一层解密即可脚本如下 import gmpy2 def share_factor(n1, n2, e, c1): p1 gmpy2.gcd(n1, n2) #gcd是求共因子用的相当于欧几里德算法的封装实现 q1 n1 / p1 q2 n2 / p1 d1 gmpy2.invert(e, (p1 - 1) * (q1 - 1)) plain gmpy2.powmod(c1, d1, n1) d2 gmpy2.invert(e, (p1 - 1) * (q2 - 1)) plain gmpy2.powmod(plain, d2, n2) plain hex(plain)[2:] if len(plain) % 2 ! 0: plain 0 plain print(Here are your plain text: \n plain.decode(hex)) if __name__ __main__: n1 115383198584677147487556014336448310721853841168758012445634182814180314480501828927160071015197089456042472185850893847370481817325868824076245290735749717384769661698895000176441497242371873981353689607711146852891551491168528799814311992471449640014501858763495472267168224015665906627382490565507927272073 n2 103835296409081751860770535514746586815395898427260334325680313648369132661057840680823295512236948953370895568419721331170834557812541468309298819497267746892814583806423027167382825479157951365823085639078738847647634406841331307035593810712914545347201619004253602692127370265833092082543067153606828049061 e 65537 c1 60406168302768860804211220055708551816238816061772464557956985699400782163597251861675967909246187833328847989530950308053492202064477410641014045601986036822451416365957817685047102703301347664879870026582087365822433436251615243854347490600004857861059245403674349457345319269266645006969222744554974358264 share_factor(n1, n2, e, c1) 最后附上别人WP的脚本(只能截图了) 不同在于我的脚本直接用p1 gmpy2.gcd(n1, n2)取公因子而他使用自定义gcd函数求公约数就是利用了前面的欧几里得算法 2021年9月绿城杯CRYPTO的RSA-1CTF-RSA-tool脚本修改、RSA通用脚本解密 下载附件是逻辑平铺类型 打开文件发现是很常规的RSA加密就是明文进行了二次处理 照例用工具CTF-RSA-tool工具首先提取出来符合CTF-RSA-tool的格式的信息先 N is 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847 e is 65537 c is 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676 运行脚本看一下回显明文必然是错误的因为M经过了二次简单乘法处理所以我们要在脚本中找到对应的地方修改一下才行 这里就属于CTF-RSA-tool工具的进阶理解了 首先根据回显DEBUG: factor N: try Common factor between ciphertext and modulus attack我在文件factor_N.py找到了对应的部分 原来是密文与模数不互素难怪我在http://www.factordb.com/index.php网站中分解不出N。而且也不是像以前积累的2021年9月广州羊城杯的BigRsa一样有两个N的模不互素 我们修改一下CTF-RSA-tool打印出p、q 然后用常规的脚本来计算试一下结果错误又出现了除数太大精度丢失了只有前缀flag了 import libnum from Crypto.Util.number import long_to_bytes q 115544353401076813303707955026809960381216232736189720201691794640724518676996765546980623105046200417460503255773857079426889487335934106430981939859723844442935408148185112500163743051467736536409887068250813490971705717411149279581182052591953379888333356928093109561978986910375048128808860432864671882543 p 150290608270992439844054823303154263794197803561695786056860615174575181277160032222859532335454486914357850849343036173838960820180867595169623670363963732315901587946639577107202780317748525709407153327463601548012321945759392416846089189522151851138821377551427960151260776474250605261723480167088408148729 e 65537 c 6944967108815437735428941286784119403138319713455732155925055928646536962597672941805831312130689338014913452081296400272862710447207265099750401657828165836013122848656839100854719965188680097375491193249127725599660383746827031803066026497989298856420216250206035068180963797454792151191071433645946245914916732637007117085199442894495667455544517483404006536607121480678688000420422281380539368519807162175099763891988648117937777951069899975260190018995834904541447562718307433906592021226666885638877020304005614450763081337082838608414756162253825697420493509914578546951634127502393647068722995363753321912676 n 17365231154926348364478276872558492775911760603002394353723603461898405740234715001820111548600914907617003806652492391686710256274156677887101997175692277729648456087534987616743724646598234466094779540729413583826355145277980479040157075453694250572316638348121571218759769533738721506811175866990851972838466307594226293836934116659685215775643285465895317755892754473332034234495795936183610569571016400535362762699517686781602302045048532131426035260878979892169441059467623523060569285570577199236309888155833013721997933960457784653262076135561769838704166810384309655788983073376941843467117256002645962737847 d libnum.invmod(e, (p - 1) * (q - 1)) #invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)(p-1)(q-1)对ψ(n)保密,也就是对应根据e*d1modψ(n),求出d #print(hex(d)) m pow(c, d, n) # 这里的m是十进制形式,pow(x, y[, z])--函数是计算 x 的 y 次方如果 z 在存在则再对结果进行取模其结果等效于 pow(x,y) %z对应前面解密算法中MD(C)C^dmod n print(long_to_bytes(m/(2021*1001*p))) 然后一开始我的思路是用在线大数除法工具解决精度丢失的问题找不到。于是进一步修改CTF-RSA-tool工具终于在RSAutils.py中找到输出结果部分修改一下成功输出flag 2021年9月绿城杯CRYPTO的RSA-2费马分解算法 下载附件是逻辑平铺类型 打开文件发现是分成两段的RSA加密第一段加密flag[:20]第二段加密flag[20:] from Crypto.Util.number import * import gmpy2 from flag import flag assert flag[:5]bflag{ m1 bytes_to_long(flag[:20]) p getPrime(512) p1 gmpy2.next_prime(p) q getPrime(512) q1 gmpy2.next_prime(q) n1 p*q*p1*q1 print(n1 ,n1) e 0x10001 c1 pow(m1,e,n1) print(c1 ,c1) m2 bytes_to_long(flag[20:]) p2 getPrime(1024) q2 getPrime(1024) print(p2q2 ,p2q2) print(q2*q2 ,p2*q2) n2 p2*p2*q2*q2*q2 print(n2 ,n2) c2 pow(m2,e,n2) print(c2 ,c2) #n1 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911 #c1 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826 #p2q2 274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778 #q2*q2 18514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217 #n2 40588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593 #c2 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647 先看第一段 gmpy2.next_prime(p)函数的意思是取邻近p的下一个素数那么很明显p和p1q和q1都是两两相邻的素数相差很小n1是2048bit级别的没法硬钢。 后半段的n2和前半段的加密逻辑差别很大所以不是两个n的模不互素。也不是像上一道题RSA1一样的密文与模数不互素。 然后查了资料后发现关键在p和p1q和q1都是两两相邻的素数这里也就是说p,q,p1,q1两两互素。单纯的factordb.com和yafu分解n肯定是分解不出来的毕竟是2048bit嘛。所以我们需要一些算法比如前面模不互素的欧几里得算法这样这里我们要用的是费马分解算法。 费马分解算法的特征就是n是4个数的乘积分解n之后我们会得到p、p1、q、q1四组隔开的排列组合但是我们的脚本可以把组合限定成 p * q1 p1 * q 和 p * q p1 * q 这样。然后通过欧几里得算法求公因子的封装函数 gcd(pq1,pq) p、gcd(p1q,p1q) q 求出两组各一个数然后就可以求出 φ(n)φ(p)⋅φ(p1)⋅φ(q)⋅φ(q1)(p−1)⋅(q−1)⋅(p1−1)⋅(q1−1) 了。 然后后面的参考以前积累的RSA解密流程做即可 费马因子分解代码 取自博客 https://blog.csdn.net/weixin_56678592/article/details/120555169?utm_mediumdistribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_linkdepth_1-utm_sourcedistribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.no_search_link import gmpy2 from gmpy2 import * from Crypto.Util.number import * import sympy e 0x10001 n1 6348779979606280884589422188738902470575876294643492831465947360363568026280963989291591157710389629216109615274754718329987990551836115660879103234129921943824061416396264358110216047994331119920503431491509529604742468032906950984256964560405062345280120526771439940278606226153077959057882262745273394986607004406770035459301695806378598890589432538916219821477777021460189140081521779103226953544426441823244765828342973086422949017937701261348963541035128661464068769033772390320426795044617751909787914185985911277628404632533530390761257251552073493697518547350246993679844132297414094727147161169548160586911 c1 6201882078995455673376327652982610102807874783073703018551044780440620679217833227711395689114659144506630609087600915116940111002026241056808189658969089532597757995423694966667948250438579639890580690392400661711864264184444018345499567505424672090632235109624193289954785503512742400960515331371813467034511130432319427185134018830006918682733848618201088649690422818940385123599468595766345668931882249779415788129316594083269412221804774856038796248038700275509397599351533280014908894068141056694660319816046357462684688942519849441237878018480036145051967731081582598773076490918572392784684372694103015244826 def fermat_factorization(n): factor_list [] get_context().precision 2048 #这里应该是n1的数量级吧len(bin(n1))就等于2048bit。 sqrt_n int(sqrt(n)) c sqrt_n while True: c 1 d_square c**2 - n if is_square(d_square): d_square mpz(d_square) get_context().precision 2048 d int(sqrt(d_square)) factor_list.append([cd,c-d]) if len(factor_list)2: break return factor_list factor_list fermat_factorization(n1) [X1,Y1] factor_list[0] #费马函数分解最大的特征就是输出两组互相交叉的p * q1 p1 * q,和p * q p1 * q我们必须用gcd(X1,X2)和gcd(Y1,Y2)求出对应的p、q [X2,Y2] factor_list[1] assert X1*Y1 n1 assert X2*Y2 n1 p1 gcd(X1,X2) q1 X1 // p1 #这是python向下取整除运算符,我真的第一次发现python有这个运算符。 p2 gcd(Y1,Y2) q2 Y1 // p2 phi1 (p1-1)*(q1-1)*(p2-1)*(q2-1) #求φ(n) d1 invert(e,phi1) #常规RSA解密流程求d print(long_to_bytes(gmpy2.powmod(c1,d1,n1)),end) #常规RSA解密流程求明文 #flag{Euler_funct1ons 结果 接下来分析后半段 后半段给了xy和x*y的值按照初中数学的逻辑直接列个方程就可以解出x和y的值了但是我看别人博客各种算法来解这个简单的逻辑什么欧拉函数因式方程看得头都晕。 然后翻着翻着突然发现一个秀儿他p2和q2求法是这样的因为n2p2*p2*q2*q2*q2所以 q2 n2 // (p2_mul_q2*p2_mul_q2)、p2 p2_mul_q2 // q2真的我都鼓掌了太棒了简单题就简单做啊简单的逻辑就应该这样求才对啊。 所以直接套用脚本即可这里要注意的是φ(n)这里因为因子只有p2和q2所以φ(n)p2*(p2 - 1)*q2*q2*(q2 - 1)只用对单个因子减1即可。 import libnum from Crypto.Util.number import long_to_bytes n240588227045595304080360385041082238507044292731344465815296032905633525556943787610712651675460810768762763493579129831271018141591546207557410817432455139315527674932933085299277599173971912445226532235814580879585317211349524406424200622675880992390782025158621241499693400288031658194434641718026910652327933253877313106112861283314274635124734817398465059373562194694957841264834312640926278890386089611103714990646541470577351599526904458342660444968591197606820361364761648205241041444681145820799054413179462285509661124362074093583494932706249461954240408827087015525507173082129412234486228092002841868365895837463699200959915782767657258729794037776401995309244941171415842403617486719492483671490834562579225506831496881542530519595438932482796867853234159664409420977526102480385193101883785161080269573707156626838551506024455480650224305894501968583442346807126920740779780593650871645915149689424292912611578291912721896864772950410266629045542480009266574096080138709683466489568290569363478444349563498507530805502511051165160827192795520182720802422213364247355775222858214648603034743679187470844212529134374975737510982287957316878179964602394749601431823167982157434890459245394370728942790117156485268116758052636794417268680901420193002289035538753620555488506926366624641291881353268617130968991258983002165300186971963661666476600998389048880565199317280428349802824448329898502788492233381873026217202981921654673840142095839603360666049476100561268336225902504932800605464136192275593886736746497955270280541423593 p2_add_q2274773146761138462708137582309097386437793891793691383033856524303010811294101933454824485010521468914846151819876043508541879637544444256520741418495479393777132830985856522008561088410862815913292288683761657919121930016956916865849261153721097671315883469348972925757078089715102032241818526925988645578778 p2_mul_q218514724270030962172566965941723224386374076294232652258701085781018776172843355920566035157331579524980108190739141959926523082142273672741849552475156278397131571360099018592018959785627785130126477982765210498547680367230723634424036009539347854344573537848628061468892166199866227984167843139793429682559241317072979374002912607549039431398267184818771503468116379618249319324788996321340764624593443106354104274472601170229835219638093242557547840060892527576940077162990069687019966946826210112318408269749294366586682732614372434218768720577917368726530200897558912687470088583774711767599580037663378929000217 e 0x10001 c2 25591090168544821761746024178724660839590948190451329227481168576490717242294520739865602061082558759751196452117720647426598261568572440942370039702932821941366792140173428488344932203576334292648255551171274828821657097667106792872200082579319963310503721435500623146012954474613150848083425126987554594651797477741828655238243550266972216752593788734836373144363217639612492397228808215205862281278774096317615918854403992620720969173788151215489908812749179861803144937169587452008097008940710091361183942268245271154461872102813602754439939747566507116519362821255724179093051041994730856401493996771276172343313045755916751082693149885922105491818225012844519264933137622929024918619477538521533548551789739698933067212305578480416163609137189891797209277557411169643568540392303036719952140554435338851671440952865151077383220305295001632816442144022437763089133141886924265774247290306669825085862351732336395617276100374237159580759999593028756939354840677333467281632435767033150052439262501059299035212928041546259933118564251119588970009016873855478556588250138969938599988198494567241172399453741709840486953189764289118312870580993115636710724139809708256360212728127786394411676427828431569046279687481368215137561500777480380501551616577832499521295655237360184159889151837766353116185320317774645294201044772828099074917077896631909654671612557207653830344897644115936322128351494551004652981550758791285434809816872381900401440743578104582305215488888563166054568802145921399726673752722820646807494657299104190123945675647 q2 n2 // (p2_mul_q2*p2_mul_q2) #//是python的除法下取整运算符 p2 p2_mul_q2 // q2 d2 libnum.invmod(e, p2*(p2 - 1)*q2*q2*(q2 - 1)) #invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)(p-1)(q-1)对ψ(n)保密,也就是对应根据e*d1modψ(n),求出d m pow(c2, d2, n2) # 这里的m是十进制形式,pow(x, y[, z])--函数是计算 x 的 y 次方如果 z 在存在则再对结果进行取模其结果等效于 pow(x,y) %z对应前面解密算法中MD(C)C^dmod n string long_to_bytes(m) # 获取m明文 print(string) 结果 2021年10月广东强网杯CRYPTO的RSA AND BASE?排列组合算法、下标对应解密 下载附件是一个txt文件打开发现RSA密文和类似base32的变码表也符合题目暗示 RSA题目照例先用CTF-RSA-TOOL工具跑一下发现跑得出来 这应该是一层的flag而且看起来像base32的四个等号联想题目和TXT文件中后面的BASE码可以猜出是BASE32变码的加密而且还有4位未知 首先通过和密文以及传统base32的码表对比可以发现缺了2 T Y Z四个字母这四个字母共有24种排列组合可以用下面代码求出排列组合 list1[2,T,Z,Y] len1len(list1) list2[] w for i in list1: for j in list1: if j!i: for k in list1: if k!j and k!i: for l in list1: if l !k and l !j and l !i: wijkl list2.append(w) print(list2) print(len(list2)) 结果 然后就是获取BASE32的编码实现来替换码表了由于我在网上找不到base32的python编码实现而且我也不会GO语言没法直接替换封装函数码表所以我用了我广州羊城杯的BabySmc技巧通过下标对应来转为传统的base32密文。 下标对应法这就要了解base32加密解密的本质了。 base32加密是5*8变8*5获取的5个8位数对应着0~32内的范围而base32的基本字符表ABCDEFGHIJKLMNOPQRSTUVWXYZ234567不过是0~32范围内对应的映射下标而已。 解密的时候也是用每个加密字符在0 ~32范围的数来拆分解密关键就是这个解密时的5位数是怎么找的呢是通过base32.index(加密字符)来找对应的0 ~ 32的下标。 所以加密字符表单的作用只是用来根据下标来映射5位数的0~32的范围而已本质是0 ~64的下标。 那么我们就可以通过一一对应的方法来把题目中新的加密表单的下标来对应原生的base32加密下标了因为base32在线解密工具只能通过base32.index(加密字符)来找0 ~ 32的下标。 脚本如下注意抽出来并且在最后要把加上去因为base32解密必须是8的倍数 import base64 #key1GHI45FQRSCX****UVWJK67DELMNOPAB3 #少了2TYZ key1GHI45FQRSCX #变形表单1 key2UVWJK67DELMNOPAB3 #变形表单2 base32ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 #传统表单 key3TCMDIEOH2MJFBLKHT2J7BLYZ2WUE5NYR2HNG #变形密文 list1[2TZY, 2TYZ, 2ZTY, 2ZYT, 2YTZ, 2YZT, T2ZY, T2YZ, TZ2Y, TZY2, TY2Z, TYZ2, Z2TY, Z2YT, ZT2Y, ZTY2, ZY2T, ZYT2, Y2TZ, Y2ZT, YT2Z, YTZ2, YZ2T, YZT2] secret for i in list1: key4key1ikey2 #最终变形表单 #print(key4) for m in key3: gkey4.index(m) secretbase32[g] secret #注意抽出来并且在最后要把加上去因为base32解密必须是8的倍数 print(secret) print(base64.b32decode(secret)) secret 结果 ECC椭圆曲线加密 攻防世界之easy_ECCECC加密 下载附件打开 椭圆曲线ECC加密没接触过不懂原理主要是找不到集成脚本算了浏览中发现一篇讲得透彻的博客 https://blog.csdn.net/weixin_30951231/article/details/95919343 这里直接使用脚本 #!/usr/bin/env python3 # -*- coding: UTF-8 -*- # Time :2020/9/28 # Author :PeterJoin import collections import random EllipticCurve collections.namedtuple(EllipticCurve, name p a b g n h) def banner(): print((%s _____ ____ ____ | ____/ ___/ ___| | _|| | | | | |__| |__| |___ |_____\____\____| %s%s # Coded By PeterJoin -椭圆曲线加密´・ω・%s % (\033[91m, \033[0m, \033[93m, \033[0m))) curve EllipticCurve( secp256k1, # Field characteristic. pint(input(p)), # Curve coefficients. aint(input(a)), bint(input(b)), # Base point. g(int(input(Gx)), int(input(Gy))), # Subgroup order. nint(input(k)), # Subgroup cofactor. h1, ) # Modular arithmetic ########################################################## def inverse_mod(k, p): Returns the inverse of k modulo p. This function returns the only integer x such that (x * k) % p 1. k must be non-zero and p must be a prime. if k 0: raise ZeroDivisionError(division by zero) if k 0: # k ** -1 p - (-k) ** -1 (mod p) return p - inverse_mod(-k, p) # Extended Euclidean algorithm. s, old_s 0, 1 t, old_t 1, 0 r, old_r p, k while r ! 0: quotient old_r // r old_r, r r, old_r - quotient * r old_s, s s, old_s - quotient * s old_t, t t, old_t - quotient * t gcd, x, y old_r, old_s, old_t assert gcd 1 assert (k * x) % p 1 return x % p # Functions that work on curve points ######################################### def is_on_curve(point): Returns True if the given point lies on the elliptic curve. if point is None: # None represents the point at infinity. return True x, y point return (y * y - x * x * x - curve.a * x - curve.b) % curve.p 0 def point_neg(point): Returns -point. assert is_on_curve(point) if point is None: # -0 0 return None x, y point result (x, -y % curve.p) assert is_on_curve(result) return result def point_add(point1, point2): Returns the result of point1 point2 according to the group law. assert is_on_curve(point1) assert is_on_curve(point2) if point1 is None: # 0 point2 point2 return point2 if point2 is None: # point1 0 point1 return point1 x1, y1 point1 x2, y2 point2 if x1 x2 and y1 ! y2: # point1 (-point1) 0 return None if x1 x2: # This is the case point1 point2. m (3 * x1 * x1 curve.a) * inverse_mod(2 * y1, curve.p) else: # This is the case point1 ! point2. m (y1 - y2) * inverse_mod(x1 - x2, curve.p) x3 m * m - x1 - x2 y3 y1 m * (x3 - x1) result (x3 % curve.p, -y3 % curve.p) assert is_on_curve(result) return result def scalar_mult(k, point): Returns k * point computed using the double and point_add algorithm. assert is_on_curve(point) if k 0: # k * point -k * (-point) return scalar_mult(-k, point_neg(point)) result None addend point while k: if k 1: # Add. result point_add(result, addend) # Double. addend point_add(addend, addend) k 1 assert is_on_curve(result) return result # Keypair generation and ECDHE ################################################ def make_keypair(): Generates a random private-public key pair. private_key curve.n public_key scalar_mult(private_key, curve.g) return private_key, public_key private_key, public_key make_keypair() print(private key:, hex(private_key)) print(public key: (0x{:x}, 0x{:x}).format(*public_key)) if __name__ __main__: banner() make_keypair() 运行之后照着输入题目附件给的参数即可 解出的xy就是flag了原理太难了以后有机会再接触。 LFSR反馈移位寄存器类型 攻防世界之streamgame1CTF中的LFSR考点(一)、文件读取对齐的二进制 下载附件是典型的LFSR类型 from flag import flag assert flag.startswith(flag{) # 作用判断字符串是否以指定字符或子字符串开头flag{ assert flag.endswith(}) # 作用判断字符串是否以指定字符或子字符串结尾}flag{}6个字节 assert len(flag)25 # flag的长度为25字节25-619个字节 #32可以这么算bin(3)0b11向左移动2位变成11000b110012(十进制) def lfsr(R,mask): output (R 1) 0xffffff #将R向左移动1位bin(0xffffff)0b1111111111111111111111110xffffff的二进制补码 i(Rmask)0xffffff #按位与运算符参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 lastbit0 while i!0: lastbit^(i1) #按位异或运算符当两对应的二进位相异时结果为1 ii1 output^lastbit return (output,lastbit) Rint(flag[5:-1],2) mask 0b1010011000100011100 fopen(key,ab) #以二进制追加模式打开 for i in range(12): tmp0 for j in range(8): (R,out)lfsr(R,mask) tmp(tmp 1)^out #按位异或运算符当两对应的二进位相异时结果为1 f.write(chr(tmp)) #chr() 用一个范围在 range256内的就是0255整数作参数返回一个对应的字符。 f.close() 明文key如下需要转成能推出初始状态值(flag)的对应位数的flag LFSR类型我在后面非传统密码类型解析中已经总结过了所以这里直接应用前面的总结步骤仿照着做即可 补充 最后的 12 内嵌 8 循环一共产生12个字符。其中的前 3 个字符的前 19 位二进制数是一个加密循环。19 位后面的数是继续用这 19 个加密后的二进制数继续新一轮加密就是多层加密。所以我们取 19 位即可结果 flag 也是 19 个二进制数。 关键就是这个key值怎么取一开始我直接复制粘贴字符转16进制然后取前19位可想而知当然是错的了 然后查了好些资料发些他们从文件中读取二进制数的代码还是不够简便于是我吸取了我前面base64编码的代码写了一串从文件中读取对齐的二进制的代码以后也直接拿来用即可。 (在线转换都会省略最开头的0导致结果位数错误进而导致结果错误所以自己要注意。) f open(5key,rb) #以二进制格式打开文件 content f.read() #读取的是\xhh类型的十六进制 key[{:08}.format(str(bin(i)).replace(0b,)) for i in content] #从base64编码汲取的经验二进制8位对齐。 print(.join(key)[:19]) 最终解题脚本还是一样要注意小端顺序 f open(5key,rb) #以二进制格式打开文件 content f.read() #读取的是\xhh类型的十六进制 key[{:08}.format(str(bin(i)).replace(0b,)) for i in content] #从base64编码汲取的经验二进制8位对齐。 key1.join(key)[:19] #lastbit全部值就是反馈函数生成的值32位的key1 key2key1 flag[] for i in range(19): output?key1[:18] #?0100000111111011110111011111000,因为后面有key1str(lastbit)key1[:31]key1不断填补output不断取前31位所以这里output每次把?定在第i位上注意output和key1是独立的分开的。 flag.append(str(int(key2[-1-i])^int(output[-3])^int(output[-4])^int(output[-5])^int(output[-9])^int(output[-13])^int(output[-14])^int(output[-17]))) #这里之所以取负数是因为我们截取是从左往右取而在计算机中是小端顺序应该从右往左取才对这里的key2[-1-i]就是小端左到右的第i位也就是前面分析的反馈函数生成值的第i位。flag值的原第i位,现在在第19位可以通过⊕的可逆性来求就是R19lastbit ⊕ R3 ⊕ R4 ⊕ R5 ⊕ R9 ⊕ R13 ⊕ R14 ⊕ R17 key1str(flag[i])key1[:18] #不断填补key1,让key1向右推进 print(flag{bin(int(.join(flag[::-1]),2)).replace(0b,)}) #这里是经过一系列操作首先把flag变成小端顺序的[::-1]然后就是转十六进制。 结果 攻防世界之streamgame2CTF中的LFSR考点(一)、文件读取对齐的二进制 下载附件还是典型的LFSR类型 from flag import flag assert flag.startswith(flag{) assert flag.endswith(}) assert len(flag)27 def lfsr(R,mask): output (R 1) 0xffffff i(Rmask)0xffffff lastbit0 while i!0: lastbit^(i1) ii1 output^lastbit return (output,lastbit) Rint(flag[5:-1],2) mask0x100002 fopen(key,ab) for i in range(12): tmp0 for j in range(8): (R,out)lfsr(R,mask) tmp(tmp 1)^out f.write(chr(tmp)) f.close() 原理同streamgame1这里唯一的不同就是mask也是要截取的因为mask要看成常数要求的是21位初始值所以24位的mask要截取成21位。 补充 最后的 12 内嵌 8 循环一共产生12个字符。其中的前 3 个字符的前 21 位二进制数是一个加密循环。21 位后面的数是继续用这 21 个加密后的二进制数继续新一轮加密就是多层加密。所以我们取 21 位即可结果 flag 也是 21 个二进制数。 直接上脚本 f open(3key,rb) #以二进制格式打开文件 content f.read() #读取的是\xhh类型的十六进制 key[{:08}.format(str(bin(i)).replace(0b,)) for i in content] #从base64编码汲取的经验二进制8位对齐。 key1.join(key)[:21] #lastbit全部值就是反馈函数生成的值32位的key1 key2key1 flag[] for i in range(21): output?key1[:20] #?0100000111111011110111011111000,因为后面有key1str(lastbit)key1[:31]key1不断填补output不断取前31位所以这里output每次把?定在第i位上注意output和key1是独立的分开的。 flag.append(str(int(key2[-1-i])^int(output[-2]))) #这里之所以取负数是因为我们截取是从左往右取而在计算机中是小端顺序应该从右往左取才对这里的key2[-1-i]就是小端左到右的第i位也就是前面分析的反馈函数生成值的第i位。flag值的原第i位,现在在第21位可以通过⊕的可逆性来求就是R21lastbit ⊕ R2 key1str(flag[i])key1[:20] #不断填补key1,让key1向右推进 print(flag{bin(int(.join(flag[::-1]),2)).replace(0b,)}) #这里是经过一系列操作首先把flag变成小端顺序的[::-1]然后就是转十六进制。 结果 js类型加密 js逻辑平铺类型 攻防世界之flag_in_your_hand1:字符串中文含义暗示、冗余中锁定关键代码 下载附件解压一个js一个html两边出击浏览器看html页面记事本看js和html的逻辑和它们之间的关系 bm函数我在js代码那里跟踪啊跟踪发现它是好多个函数的嵌套没办法了根本不知道关键逻辑放在哪里。查了资料说看跟踪ic真是一语惊醒梦中人ic是判断条件归根结底还是判断ic,找ic即可 找到ic了这个ic也的确在bm函数嵌套内由于在学逆向所以直接写逆向脚本即可 key1[118, 104, 102, 120, 117, 108, 119, 124, 48,123,101,120] token for i in key1: tokenchr(i-3) print(token) 结果 最后回顾一下为什么下面这个每次都有且每次都不一样呢观察js代码可以发现每个js函数的接受参数s就是我们传入token而fg生成函数bm嵌套了很多函数所以直接逆向bm函数生成flag不现实而参数token作为s传入后就会加密回显所以输入错误的token也会显示出不同的加密串 python类型逻辑加密 pyc文件反编译 攻防世界之easychallenge源代码修改逻辑解密、 下载附件是pyc文件于是要反编译一开始看资料说用uncompyle6我也不知道为什么我的老是报错后来又找了个在线反编译可以支持的Python版本比较多 https://tool.lu/pyc/ 反编译代码 #!/usr/bin/env python # visit https://tool.lu/pyc/ for more information import base64 def encode1(ans): s for i in ans: x ord(i) ^ 36 x x 25 s chr(x) return s def encode2(ans): s for i in ans: x ord(i) 36 x x ^ 36 s chr(x) return s def encode3(ans): return base64.b32encode(ans) flag print Please Input your flag: flag raw_input() final UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E if encode3(encode2(encode1(flag))) final: print correct else: print wrong 本来是自己一层层改的怎么加密就怎么逆过来解密后来发现又犯了以前的错误有源码就要用源码啊 直接在源码上修改即可 #!/usr/bin/env python # visit https://tool.lu/pyc/ for more information import base64 def decode1(ans): s for i in ans: x ord(i) -25 x x ^ 36 s chr(x) return s def decode2(ans): s for i in ans: x i ^ 36 x x - 36 s chr(x) return s def decode3(ans): return base64.b32decode(ans) final UC7KOWVXWVNKNIC2XCXKHKK2W5NLBKNOUOSK3LNNVWW3E print(decode1(decode2(decode3(final))) ) 传统密码类型解析 凯撒密码(24个字母) 特点:24个字母间的移动 在密码学中恺撒密码英语Caesar cipher或称恺撒加密、恺撒变换、变换加密是一种最简单且最广为人知的加密技术。它是一种替换加密的技术明文中的所有字母都在字母表上向后或向前按照一个固定数目进行偏移后被替换成密文。例如当偏移量是3的时候所有的字母A将被替换成DB变成E以此类推。 加密就是明文向后移动展现出对应的密文。 解密就是密文向前移动展现出对应的明文。 明文字母表 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 密文字母表 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z 摩斯密码(只有01(无规则)或.-空格或/做分隔符) 摩尔斯电码也被称作摩斯密码是一种时通时断的信号代码通过不同的排列顺序来表达不同的英文字母、数字和标点符号。它发明于1837年是一种早期的数字化通信形式。不同于现代化的数字通讯摩尔斯电码只使用零和一两种状态的二进制代码它的代码包括五种短促的点信号“・”读“滴”Di保持一定时间的长信号“-”读“嗒”Da表示点和划之间的停顿、每个词之间中等的停顿以及句子之间长的停顿。 摩斯电码格式要求可用空格或单斜杠/来分隔摩斯电码但只可用一种不可混用 云影密码(01248) 此密码运用了1248代码,因为本人才疏学法,问未发现有过使用的先例,因此暂归为原创密码。由于这个密码,我和片风云影初识,为了纪念,将其命名为“云影密码”。 有了1,2,4,8这四个苘单的数字,你可以以加法表示出0~9任何个数字,例如028,7124,918这样,再用1-26来表示A-Z,就可以用作密码了。为了不至于混乱,我个人引入了第五个数字0,来用作间隔,以遍免翻译错误,所以还可以称“01248密码” 注意(3个及以上数字时) 虽然是相加但是可以在数字内不按顺序相加如124可写成(12)4和1(24)结果分别是7和16只要保证不大于26即可 题目(总不超过26) 12401011801180212011401804 第一步分割 即124 、1、118、118、212、114、18、4 第二步基本翻译 例如124可以表示7,也可以表示16(但不可能是34,因为不会超过26),所以可以放弃来翻译其他没有异议的,可得:124、a、s、s、w、o、18、d 第三步推测得出明文 可以推测后面的18表示r,前面的为p最合适。 所以最后明文: password(密码) 栅栏密码(分组数作密钥) 所谓栅栏密码就是把要加密的明文分成N个一组然后把每组的第1个字连起来形成一段无规律的话。 不过栅栏密码本身有一个潜规则就是组成栅栏的字母一般不会太多。一般不超过30个也就是一、两句话 传统栅栏密码(矩阵行列密钥是行数) 假如有一个字符串123456789 取字符串长度的因数进行分组假如key3 1 2 3 \\分组情况每三个数字一组分为三组 4 5 6 7 8 9 然后每一组依次取一个数字组成一个新字符串147258369 \\加密完成的字符串 解题 试一般的栅栏密码,取5为矩阵行数,得到 cyperrocaegireeol} eahfocec gnbip不正确取5为矩阵列数,得到 cebgccfe en eohplprgecrayoii aoreg”,也不正确除了常规的栅栏密码,还有一种w型的栅栏密码。 w型的栅栏密码(第一行是Key数后面排成w型横竖读取) 同样一个字符串123456789 key3 1----5----9 \\让数字以W型组织同样是三组但每组的数量不一定相同 -2--4-6--8 --3----7-- 加密密文159246837 解题 题目提示:栅栏密码,密钥长度为5 是将明文按照w型排列,并横(竖)向读取密文,其解密过程就是加密的逆过程,即将密文横(竖)向按一定规律排列后,以w型读取,对于此题,根据题目提示为以下5行。 培根密码(大小写的ABab而且必须是5个一组不是5个就考虑摩斯密码): 培根所用的密码是一种本质上用二进制数设计的没有用通常的0和1来表示而是采用a和b 培根密码加密方式 第一种方式 A aaaaa B aaaab C aaaba D aaabb E aabaa F aabab G aabba H aabbb I abaaa J abaab K ababa L ababb M abbaa N abbab O abbba P abbbb Q baaaa R baaab S baaba T baabb U babaa V babab W babba X babbb Y bbaaa Z bbaab 第二种方式: a AAAAA g AABBA n ABBAA t BAABA b AAAAB h AABBB o ABBAB u-v BAABB c AAABA i-j ABAAA p ABBBA w BABAA d AAABB k ABAAB q ABBBB x BABAB e AABAA l ABABA r BAAAA y BABBA f AABAB m ABABB s BAAAB z BABBB 举例 例1、 baabaaabbbabaaabbaaaaaaaaabbabaaaabaaaaaabaaabaabaaaabaabbbaabbbaababb baaba aabbb abaaa bbaaa aaaaa abbab aaaab aaaaa abaaa baaba  aaaba abbba abbba ababb s           h         i           y         a         n         b         a        i           s          c         o          o        l  附加解密Python脚本如下 #!/usr/bin/python # -*- coding: utf-8 -*- import re alphabet [a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z] first_cipher [aaaaa,aaaab,aaaba,aaabb,aabaa,aabab,aabba,aabbb,abaaa,abaab,ababa,ababb,abbaa,abbab,abbba,abbbb,baaaa,baaab,baaba,baabb,babaa,babab,babba,babbb,bbaaa,bbaab] second_cipher [aaaaa,aaaab,aaaba,aaabb,aabaa,aabab,aabba,aabbb,abaaa,abaaa,abaab,ababa,ababb,abbaa,abbab,abbba,abbbb,baaaa,baaab,baaba,baabb,baabb,babaa,babab,babba,babbb] def encode(): string raw_input(please input string to encode:\n) #这里接收要加密的字符串 e_string1 e_string2 for index in string: for i in range(0,26): if index alphabet[i]: e_string1 first_cipher[i] e_string2 second_cipher[i] break print first encode method result is:\ne_string1 print second encode method result is:\ne_string2 return def decode(): e_string raw_input(please input string to decode:\n) #这里接收要解密的字符串 e_array re.findall(.{5},e_string) d_string1 d_string2 for index in e_array: for i in range(0,26): if index first_cipher[i]: d_string1 alphabet[i] if index second_cipher[i]: d_string2 alphabet[i] print first decode method result is:\nd_string1 print second decode method result is:\nd_string2 return if __name__ __main__: while True: print \t*******Bacon Encode_Decode System******* print input should be lowercase,cipher just include a b print 1.encode\n2.decode\n3.exit s_number raw_input(please input number to choose\n) if s_number 1: encode() raw_input() elif s_number 2: decode() raw_input() elif s_number 3: break else: continue 与佛论禅编码要加上佛曰才能转换(BASE64类型转不了就ROT13一下) 网址 与佛论禅 题目文字 夜哆悉諳多苦奢陀奢諦冥神哆盧穆皤三侄三即諸諳即冥迦冥隸數顛耶迦奢若吉怯陀諳怖奢智侄諸若奢數菩奢集遠俱老竟寫明奢若梵等盧皤豆蒙密離怯婆皤礙他哆提哆多缽以南哆心曰姪罰蒙呐神。舍切真怯勝呐得俱沙罰娑是怯遠得呐數罰輸哆遠薩得槃漫夢盧皤亦醯呐娑皤瑟輸諳尼摩罰薩冥大倒參夢侄阿心罰等奢大度地冥殿皤沙蘇輸奢恐豆侄得罰提哆伽諳沙楞缽三死怯摩大蘇者數一遮 转换后的 MzkuM3gvMUAwnzuvn3cgozMlMTuvqzAenJchMUAeqzWenzEmLJW9 的确是BASE64类型但是直接BASE64是转换不出来的还要先ROT13一下可以算是一个小混淆长见识了。 转轮机加密 特点是等长的分好组的乱序字母原理是转齿轮把一个字母换成另一个来拼成一句话。 格式是这样的 脚本解题积累 rotor [ #这里是要输入的转轮机原始字符串 ZWAXJGDLUBVIQHKYPNTCRMOSFE, KPBELNACZDTRXMJQOYHGVSFUWI, BDMAIZVRNSJUWFHTEQGYXPLOCK, RPLNDVHGFCUKTEBSXQYIZMJWAO, IHFRLABEUOTSGJVDKCPMNZQWXY, AMKGHIWPNYCJBFZDRUSLOQXVET, GWTHSPYBXIZULVKMRAFDCEONJQ, NOZUTWDCVRJLXKISEFAPMYGHBQ, XPLTDSRFHENYVUBMCQWAOIKZGJ, UDNAJFBOWTGVRSCZQKELMXYIHP, MNBVCXZQWERTPOIUYALSKDJFHG, LVNCMXZPQOWEIURYTASBKJDFHG, JZQAWSXCDERFVBGTYHNUMKILOP ] cipher NFQKSEVOQOFNP #这是要输入转轮机密文 key [2,3,7,5,13,12,9,1,8,10,4,11,6] #这是要输入转轮机密钥 tmp_list[] for i in range(0, len(rotor)): tmp k key[i] - 1 for j in range(0, len(rotor[k])): if cipher[i] rotor[k][j]: if j 0: tmprotor[k] break else: tmprotor[k][j:] rotor[k][0:j] break tmp_list.append(tmp) # print(tmp_list) message_list [] for i in range(0, len(tmp_list[i])): tmp for j in range(0, len(tmp_list)): tmp tmp_list[j][i] message_list.append(tmp) print(message_list) def spread_list(lst): for item in lst: if isinstance(item,(list,tuple)): yield from spread_list(item) else: yield item pass if __name__ __main__: for i in spread_list(message_list): print(**25) print(i) #在多个输出中查找有语义的字符串即为flag内容 键盘密码 键盘密码应该不算是一种加密算法但是一种有趣的设置密码方式。他就是a-z(A-Z)对应成键盘上的字母把键盘字母一行一行的对应即可。包围的键就是要找的值。 每个围起来的圈之间通常会有明显的间隔比如空格。如r5yG lp9I BjM tFhB T6uh y7iJ QsZ bhM poem codes诗歌加密 (内容地址出处)https://blog.csdn.net/weixin_45530599/article/details/108027293 ① 给出一首诗歌 for my purpose holds to sail beyond the sunset, and the baths of all the western stars until I die. ② 给出5个关键单词。 “for”, “sail”, “all”, “stars”, “die.” 对其进行拆散 f o r s a i l a l l s t a r s d i e 接下来按照 字母表顺序 进行编号若遇相同字母则继续 1 ③ 将要传递的消息进行加密。 We have run out of cigars, situation desperate。 先对其进行编码。因为给出的5个关键词其长度为18.所以以18为一组。 若一组长度不满18则用abc(不要求有序)进行补充。 将排好的消息按照之前给出的诗歌字母编号写下密文。 for my purpose holds to sail beyond the sunset, and the baths of all the western stars until I die. 如 for -- eud tdk oek 那么得到的又可以按照5个适当个数为一组进行重新分组得到最后密文。 我的看法 其实排序逻辑挺常规的就是诗歌 -- 关键词原文 -- 参照顺序排列密文 -- 按诗歌关键词对原文映射取值。 解题脚本 用github的脚本(单独复制poemcode.py是会报错的因为文件中有其他依靠) git clone git://github.com/abpolym/crypto-tools 用法(python2ctfpoem是诗歌ctfcip是加密密文) python2 poemcode.py examples/2/ctfpoem examples/2/ctfcip URL编码规则 URL 编码使用 % 其后跟随两位的十六进制数来替换非 ASCII 字符。 ASCII Value URL-encode ASCII Value URL-encode ASCII Value URL-encode ASCII Value URL-encode ASCII Value URL-encode ASCII Value URL-encode NULL结束符 %00 0 %30 %60 %90 À %c0 ð %f0 %01 1 %31 a %61 ‘ %91 Á %c1 ñ %f1 %02 2 %32 b %62 ’ %92  %c2 ò %f2 %03 3 %33 c %63 “ %93 à %c3 ó %f3 %04 4 %34 d %64 ” %94 Ä %c4 ô %f4 %05 5 %35 e %65 • %95 Å %c5 õ %f5 %06 6 %36 f %66 – %96 Æ %c6 ö %f6 %07 7 %37 g %67 — %97 Ç %c7 ÷ %f7 backspace %08 8 %38 h %68 ˜ %98 È %c8 ø %f8 tab %09 9 %39 i %69 ™ %99 É %c9 ù %f9 换行符 %0a : %3a j %6a š %9a Ê %ca ú %fa %0b ; %3b k %6b › %9b Ë %cb û %fb %0c %3c l %6c œ %9c Ì %cc ü %fc c return %0d %3d m %6d %9d Í %cd ý %fd %0e %3e n %6e ž %9e Î %ce þ %fe %0f ? %3f o %6f Ÿ %9f Ï %cf ÿ %ff %10 %40 p %70 %a0 Ð %d0 %11 A %41 q %71 ¡ %a1 Ñ %d1 %12 B %42 r %72 ¢ %a2 Ò %d2 %13 C %43 s %73 £ %a3 Ó %d3 %14 D %44 t %74 %a4 Ô %d4 %15 E %45 u %75 ¥ %a5 Õ %d5 %16 F %46 v %76 | %a6 Ö %d6 %17 G %47 w %77 § %a7 %d7 %18 H %48 x %78 ¨ %a8 Ø %d8 %19 I %49 y %79 © %a9 Ù %d9 %1a J %4a z %7a ª %aa Ú %da %1b K %4b { %7b « %ab Û %db %1c L %4c | %7c ¬ %ac Ü %dc %1d M %4d } %7d ¯ %ad Ý %dd %1e N %4e ~ %7e ® %ae Þ %de %1f O %4f %7f ¯ %af ß %df 空格 %20 P %50 € %80 ° %b0 à %e0 ! %21 Q %51 %81 ± %b1 á %e1 %22 R %52 ‚ %82 ² %b2 â %e2 # %23 S %53 ƒ %83 ³ %b3 ã %e3 $ %24 T %54 „ %84 ´ %b4 ä %e4 % %25 U %55 … %85 µ %b5 å %e5 %26 V %56 † %86 ¶ %b6 æ %e6 %27 W %57 ‡ %87 · %b7 ç %e7 ( %28 X %58 ˆ %88 ¸ %b8 è %e8 ) %29 Y %59 ‰ %89 ¹ %b9 é %e9 * %2a Z %5a Š %8a º %ba ê %ea %2b [ %5b ‹ %8b » %bb ë %eb , %2c \ %5c Œ %8c ¼ %bc ì %ec - %2d ] %5d %8d ½ %bd í %ed . %2e ^ %5e Ž %8e ¾ %be î %ee / %2f _ %5f %8f ¿ %bf ï %ef 仿射密码 仿射密码是一种替换密码它是一个字母对一个字母的。为单表加密的一种字母系统中所有字母都藉一简单数学方程加密对应至数值或转回字母。 其仍有所有替代密码之弱处。所有字母皆借由方程加密b为移动大小。 在仿射加密中大小为m之字母系统首先对应至0..m-1范围内之数值 接着使用模数算数来将原文件中之字母转换为对应加密文件中的数字。 其实这有点像我的base64表单下标替换 它的加密函数是其中a和m互质m是字母的数目 解密函数是 补充求集合Z上数x的逆元的 gmpy2.invert(x,Z) 或 libnum.invmode(e,(p-1)*(q-1)) a之乘法逆元素仅存在于a与m互质条件下。 由此没有a的限制可能无法解密。 易知解密方程逆于加密方程 非传统密码类型解析 CTF中的LFSR考点(一) 前提概要 这是我在理解了作者道路结冰的博客深入分析CTF中的LFSR类题目一下写的一次回顾和分析只是在其中加上自己的见识和理解来加深印象。 博客地址 深入分析CTF中的LFSR类题目一 - 安全客安全资讯平台 前言: LFSR线性反馈移位寄存器已经成为如今CTF中密码学方向题目的一个常见考点了在今年上半年的一些国内赛和国际赛上也出现了非常多的这类题目但是其中绝大多数题目目前都没有writeups或者writeups并没有做cryptanalysis而是通过爆破的方法解决这种思路只适用于部分类似去年强网杯出现的几道非常基础的LFSR类题目有效对于绝大多数国际赛上的题目不仅是没有任何效果的也是没有任何意义的只有真正掌握了LFSR的密码学原理才有可能在国际赛上解决一道高分值的LFSR类题目网上针对这类考点的详细分析也不多因此接下来我将通过几篇文章对这类知识点进行一个详细的分析。 LFSR简介 LFSR简介 LFSR是属于FSR反馈移位寄存器的一种除了LFSR之外还包括NFSR非线性反馈移位寄存器。 附加 反馈移位就是可以通过前面已经存在的寄存器中的值反馈出后面的的寄存器的值通过不断移位对应不同的前寄存器值一直反馈出后面连续的后寄存器值。 FSR是流密码产生密钥流的一个重要组成部分在GF(2)上的一个n级FSR通常由n个二元存储器和一个反馈函数组成如下图所示 如果这里的反馈函数是线性的我们则将其称为LFSR此时该反馈函数可以表示为 其中cn0或1⊕表示异或模二加也就是说反馈函数必然为a1……⊕……an形式中的一部分 我们接下来通过一个例子来更直观的明确LFSR的概念 假设给定一个5级的LFSR其初始状态即a1到a5这5个二元存储器的值为 其反馈函数为 整个过程可以表示为下图所示的形式 接下来我们来计算该LFSR的输出序列输出序列的前5位即为我们的初始状态10011第6位的计算过程如下 第7位的计算过程如下: 由此类推可以得到前31位的计算结果如下 1001101001000010101110110001111 对于一个 n 级的LFSR来讲其最大周期为2^n-1 因此对于我们上面的 5 级 LFSR 来讲其最大周期为 2^5-131再后面的输出序列即为前 31 位的循环。 注意 这里的级就是能通过反馈函数生成完整连续序列的最少寄存器数因为a6a1⊕a4所以a5必须包含在内所以是5级寄存器。 通过上面的例子我们可以看到对于一个LFSR来讲我们目前主要关心三个部分 初始状态、反馈函数和输出序列。 CTF的LFSR题目示例 那么对于CTF中考察LFSR的题目来讲也是如此大多数情况下我们在CTF中的考察方式都可以概括为 给出反馈函数和输出序列要求我们反推出初始状态初始状态即为我们需要提交的flag另外大多数情况下初始状态的长度我们也是已知的。 显然这个反推并不是一个容易的过程尤其当反馈函数十分复杂的时候接下来我们就通过一些比赛当中出现过的具体的CTF题目来看一下在比赛当中我们应该如何解决这类问题由于不同题目之间难度差异会很大所以我们先从最简单的题目开始我将尽可能的用最通俗的语言和脚本来进行演示在后面会逐渐提升题目的难度同时补充相应的代数知识。 2018 CISCN 线上赛 oldstreamgame 题目给出的脚本如下 flag flag{xxxxxxxxxxxxxxxx} assert flag.startswith(flag{) assert flag.endswith(}) assert len(flag)14 def lfsr(R,mask): output (R 1) 0xffffffff i(Rmask)0xffffffff lastbit0 while i!0: lastbit^(i1) ii1 output^lastbit return (output,lastbit) Rint(flag[5:-1],16) mask 0b10100100000010000000100010010100 fopen(key,w) for i in range(100): tmp0 for j in range(8): (R,out)lfsr(R,mask) tmp(tmp 1)^out f.write(chr(tmp)) f.close() 分析一下我们的已知条件1 已知初始状态的长度为4个十六进制数即32位初始状态的值即我们要去求的flag所以初步判断这里的级是32那么最大周期就是2^32-1。 已知反馈函数lfsr只不过这里的反馈函数是代码的形式我们需要提取出它的数学表达式。 已知输出序列。 那么我们的任务很明确就是通过分析lfsr函数整理成数学表达式的形式求解即可接下来我们一行一行的来分析这个函数 把反馈函数从代码形式整理成反馈函数表达式 通过上面的分析我们可以看出在这道题的情境下lfsr函数本质上就是一个输入R输出lastbit的函数虽然我们现在已经清楚了R是如何经过一系列运算得到lastbit的但是我们前面的反馈函数都是数学表达式的形式我们能否将上述过程整理成一个表达式的形式呢这就需要我们再进一步进行分析 mask只有第3、5、8、12、20、27、30、32这几位为1其余位均为0。 mask与R做按位与运算得到i当且仅当R的第3、5、8、12、20、27、30、32这几位中也出现1时i中才可能出现1否则i中将全为0。 lastbit是由 i 的最低位向i的最高位依次做异或运算得到的在这个过程中所有为 0 的位我们可以忽略不计因为0异或任何数等于任何数本身不影响最后运算结果因此lastbit的值仅取决于 i 中有多少个1当i中有奇数个1时lastbit等于1当i中有偶数个1时lastbit等于0。 当R的第3、5、8、12、20、27、30、32这几位依次异或结果为1时即R中有奇数个1因此将导致 i 中有奇数个1当R的第3、5、8、12、20、27、30、32这几位依次异或结果为0时即R中有偶数个1因此将导致 i 中有偶数个1。 因此我们可以建立出联系lastbit等于R的第3、5、8、12、20、27、30、32这几位依次异或的结果。 将其写成数学表示式的形式即为我们要求的反馈函数反馈函数的形式也说明了初始位数要32位 然后我们看一下明文key是怎么来的 key20FDEEF8A4C9F4083F331DA8238AE5ED083DF0CB0E7A83355696345DF44D7C186C1F459BCE135F1DB6C76775D5DCBAB7A783E48A203C19CA25C22F60AE62B37DE8E40578E3A7787EB429730D95C9E1944288EB3E2E747D8216A4785507A137B413CD690C 最后八行代码对flag它做了一百次循环每次循环内都嵌套了8位的循环来产生一个结果字符并将这个结果写到key里面去所以key里面总共有一百个ASCII字符共两百个16进制数。4位为1个16进制数1个字符byte是8位 补充 题目之所以会出现 100 个ASCII字符是因为 4 循环次加内嵌的 8 位一次共 32 位循环往后产生的 4 个flag生成的加密字符共 8 个 16 进制数后继续用这 4 个加密后的 flag 字符继续新一轮加密就是多层加密。所以我们取 32 位即可结果 flag 也是 4 个ASCII字符拆分出的 8 个 16 进制数。 显然lastbit和R之间满足线性关系那么接下来我们就可以开始求解了 而且从这里我们可以知道这种移位的CTF题目类型要反推32位的初始值要多少位输出序列呢答案就是32位因为这种移位的题目是32位为一个循环这就和我们前面说的2^32-1的循环不太同了因为这里是移位操作。 32位Key值00100000111111011110111011111000 解题的关键是发现在明文只剩最后一位时,可以通过最后的结果来求出排在第32位的第一位然后就可以反推回去了。 我们想象这样一个场景当即将输出第32位lastbit时此时R已经左移了31位根据上面的数学表达式我们有 这样我们就可以求出R的第1位同样的方法我们可以求出R的第2位 以此类推R的全部32位我们都可以依次求出了。 最终脚本这里注意小端顺序的反序取位 key100100000111111011110111011111000 #lastbit全部值就是反馈函数生成的值32位的key1 key2key1 flag[] for i in range(32): output?key1[:31] #?0100000111111011110111011111000,因为后面有key1str(lastbit)key1[:31]key1不断填补output不断取前31位所以这里output每次把?定在第i位上注意output和key1是独立的分开的。 flag.append(str(int(key2[-1-i])^int(output[-3])^int(output[-5])^int(output[-8])^int(output[-12])^int(output[-20])^int(output[-27])^int(output[-30]))) #这里之所以取负数是因为我们截取是从左往右取而在计算机中是小端顺序应该从右往左取才对这里的key2[-1-i]就是小端左到右的第i位也就是前面分析的反馈函数生成值的第i位。flag值的原第i位,现在在第32位可以通过⊕的可逆性来求就是R32lastbit ⊕ R3 ⊕ R5 ⊕ R8 ⊕ R12 ⊕ R20 ⊕ R27 ⊕ R30 key1str(flag[i])key1[:31] #不断填补key1,让key1向右推进 print(flag{hex(int(.join(flag[::-1]),2)).replace(0x,)}) #这里是经过一系列操作首先把flag变成小端顺序的[::-1]然后就是转十六进制。 结果 解密工具、脚本积累 Ciphey工具 Ciphey 是一个使用自然语言处理和人工智能的全自动解密/解码/破解工具只需要输入加密文本它就能给你返回解密文本。 Ciphey 基本使用 文件输入 ciphey -f encrypted.txt # 或 python -m ciphey -f encrypted.txt 不规范的方法 ciphey -- Encrypted input # 或 python -m ciphey -- Encrypted input 正常方式 ciphey -t Encrypted input # 或 python -m ciphey -t Encrypted input 要去除进度条、概率表和所有噪音请使用安静模式 ciphey -t encrypted text here -q Ciphey 支持解密的密文和编码多达51种下面列出一些基本的选项基本密码 Caesar Cipher ROT47 (up to ROT94 with the ROT47 alphabet) ASCII shift (up to ROT127 with the full ASCII alphabet) Vigenère Cipher Affine Cipher Binary Substitution Cipher (XY-Cipher) Baconian Cipher (both variants) Soundex Transposition Cipher Pig Latin 现代密码学 Repeating-key XOR Single XOR 编码 Base32 Base64 Z85 (release candidate stage) Base65536 (release candidate stage) ASCII Reversed text Morse Code DNA codons (release candidate stage) Atbash Standard Galactic Alphabet (aka Minecraft Enchanting Language) Leetspeak Baudot ITA2 URL encoding SMS Multi-tap DMTF (release candidate stage) UUencode Braille (Grade 1) Ciphey 的功能不仅于本文介绍的这些本文所介绍的只是冰山一角它还可以添加属于你自己的解码器 https://github.com/Ciphey/Ciphey/wiki/Adding-your-own-ciphers CTF-RSA-tool工具 RSA前景知识 RSA公开密钥密码体制是一种使用不同的加密密钥与解密密钥“由已知加密密钥推导出解密密钥在计算上是不可行的”密码体制 。 在公开密钥密码体制中加密密钥即公开密钥PK是公开信息而解密密钥即秘密密钥SK是需要保密的。加密算法E和解密算法D也都是公开的。虽然解密密钥SK是由公开密钥PK决定的但却不能根据PK计算出SK [2] 。 RSA公开密钥密码体制的原理是根据数论寻求两个大素数比较简单而将它们的乘积进行因式分解却极其困难因此可以将乘积公开作为加密密钥 [4] 。 RSA脚本工具使用说明 usage: solve.py [-h] 用法solve.py[-h] (--decrypt DECRYPT | -c DECRYPT_INT | --private | -i INPUT | -g) [--createpub] [-o OUTPUT] [--dumpkey] [--enc2dec ENC2DEC] [-k KEY] [-N N] [-e E] [-d D] [-p P] [-q Q] [--KHBFA KHBFA][--pbits PBITS] [-v] It helps CTFer to get first blood of RSA-base CTF problems 它有助于CTFer获得RSA基础CTF问题的第一滴血 -v, --verbose print details 详细的打印细节 optional arguments:可选参数(注意这里之间只可选一个且必选一个) -h, --help show this help message and exit --帮助显示此帮助消息并退出 --decrypt DECRYPT decrypt a file, usually like flag.enc 解密文件通常类似于“flag.enc” (通常搭配k的.pem或.pub一起使用) -c DECRYPT_INT, --decrypt_int DECRYPT_INT 解密长整形数 --private Print private key if recovered 打印私钥如果已解密 -i INPUT input a file with all necessary parameters (see examples/input_example.txt) 输入包含所有必要参数的文件请参见示例/输入示例.txt -g, --gadget Use some gadgets to pre-process your data first 使用一些小工具先预处理数据 some gadgets:一些小工具预处理数据(全部可选) --createpub Take N and e and output to file specified by -o or just print it 获取N和e并输出到由“-o”指定的文件或者直接打印出来就行了 -o OUTPUT, --output OUTPUT 输出 Specify the output file path in --createpub mode. 在--createpub模式下指定输出文件路径。 --dumpkey Just print the RSA variables from a key - n,e,d,p,q 只打印一个key-n、e、d、p、q中的RSA变量 --enc2dec ENC2DEC get cipher (in decimalism) from a encrypted file 从加密文件中获取密码十进制 the RSA variables:RSA变量Specify the variables whatever you got指定您得到的变量(全部可选实验中发现输入时只能用N、e参数进行命令行输入) -k KEY, pem file, usually like .pub or .pem, and it begins with -----BEGIN pem文件通常类似于“.pub”或“.pem”并以“-----BEGIN”开始 -N N the modulus 模量 -e E the public exponent 公共指数 -d D the private exponent 私人指数 -p P one factor of modulus 模量的一个因子 -q Q one factor of modulus 模量的一个因子 extra variables:额外变量Used in some special methods 在一些特殊的方法中使用 --KHBFA KHBFA use Known High Bits Factor Attack, this specify the High Bits of factor 使用已知的高位因子攻击这指定因子高位 --pbits PBITS customize the bits lenth of factor, default is half of ns bits lenth 自定义因子的位长度默认值为ns比特长度 多组n,e,c在解题时长这个样子 可以看到特征真的就是多个nec甚至还有d且不管这里的n,e,c是大还是小长还是短都列入多组n,e,c类型里。 一组n,e,c的题目样式 从这里可以看到一组,n,e,c里面甚至可以没有c这里的n,e,c也不管大小长短这里最后一个hbop的解题要用到前面说得sagemath这里暂且不说。 不同情景下工具运行示例 补充 单个n,e,c,q,p,的时候最好用单个参数输入的方式不要用文本读取的方式因为文本读取的时候DEBUG显示的十六进制的d有时并不是我们想要的 # 只需要一组密钥的 # wiener_attack python2 solve.py --verbose -i examples/wiener_attack.txt # 或者通过命令行只要指定对应参数就行了 python2 solve.py --verbose --private -N 460657813884289609896372056585544172485318117026246263899744329237492701820627219556007788200590119136173895989001382151536006853823326382892363143604314518686388786002989248800814861248595075326277099645338694977097459168530898776007293695728101976069423971696524237755227187061418202849911479124793990722597 -e 354611102441307572056572181827925899198345350228753730931089393275463916544456626894245415096107834465778409532373187125318554614722599301791528916212839368121066035541008808261534500586023652767712271625785204280964688004680328300124849680477105302519377370092578107827116821391826210972320377614967547827619 # factordb.com python2 solve.py --verbose -k examples/jarvis_oj_mediumRSA/pubkey.pem --decrypt examples/jarvis_oj_mediumRSA/flag.enc # Boneh and Durfee attack # TODO: get an example public key solvable by boneh_durfee but not wiener # small q attack python2 solve.py --verbose --private -k examples/small_q.pub # 2017强网杯线上赛 RSA 费马分解pq相近时 python2 solve.py --verbose -i examples/closed_p_q.txt # Common factor between ciphertext and modulus attack python2 solve.py --verbose -k examples/common_factor.pub --decrypt examples/common_factor.cipher # small e python2 solve.py --verbose -k examples/small_exponent.pub --decrypt examples/small_exponent.cipher # rabin method when e 2 python2 solve.py --verbose -k examples/jarvis_oj_hardRSA/pubkey.pem --decrypt examples/jarvis_oj_hardRSA/flag.enc # Small fractions method when p/q is close to a small fraction python2 solve.py --verbose -k examples/smallfraction.pub --private # Known High Bits Factor Attack python2 solve.py --verbose -i examples/KnownHighBitsFactorAttack.txt # 需要多组密钥的 # 第三届上海市大学生网络安全大赛--rrrsa d泄漏攻击 python2 solve.py --verbose -i examples/d_leak.txt # 模不互素 模不互素是给你两个单独分解不了的大数级n方便让你求公因子。然后只用一个n来加密对只用一个n。 python2 solve.py --verbose -i examples/share_factor.txt # 共模攻击 python2 solve.py --verbose -i examples/share_N.txt # Basic Broadcast Attack(低加密指数广播攻击) python2 solve.py --verbose -i examples/Basic_Broadcast_Attack.txt RSA通用的简单脚本已知p、q、e、c值 import libnum from Crypto.Util.number import long_to_bytes q int( 0xa6055ec186de51800ddd6fcbf0192384ff42d707a55f57af4fcfb0d1dc7bd97055e8275cd4b78ec63c5d592f567c66393a061324aa2e6a8d8fc2a910cbee1ed9, 16) p int( 0xfa0f9463ea0a93b929c099320d31c277e0b0dbc65b189ed76124f5a1218f5d91fd0102a4c8de11f28be5e4d0ae91ab319f4537e97ed74bc663e972a4a9119307, 16) e int( 0x6d1fdab4ce3217b3fc32c9ed480a31d067fd57d93a9ab52b472dc393ab7852fbcb11abbebfd6aaae8032db1316dc22d3f7c3d631e24df13ef23d3b381a1c3e04abcc745d402ee3a031ac2718fae63b240837b4f657f29ca4702da9af22a3a019d68904a969ddb01bcf941df70af042f4fae5cbeb9c2151b324f387e525094c41, 16) c 0x7fe1a4f743675d1987d25d38111fae0f78bbea6852cba5beda47db76d119a3efe24cb04b9449f53becd43b0b46e269826a983f832abb53b7a7e24a43ad15378344ed5c20f51e268186d24c76050c1e73647523bd5f91d9b6ad3e86bbf9126588b1dee21e6997372e36c3e74284734748891829665086e0dc523ed23c386bb520 n q * p d libnum.invmod(e, (p - 1) * (q - 1)) #invmod(a, n) - 求a对于n的模逆,这里逆向加密过程中计算ψ(n)(p-1)(q-1)对ψ(n)保密,也就是对应根据ed1modψ(n),求出d m pow(c, d, n) # pow(x, y[, z])--函数是计算 x 的 y 次方如果 z 在存在则再对结果进行取模其结果等效于 pow(x,y) %z对应前面解密算法中MD(C)C^d(mod n) #print(m) #明文的十进制格式 string long_to_bytes(m) # m明文用长字节划范围 print(string.decode()) ECC加密 介绍 椭圆曲线密码学英语Elliptic curve cryptography缩写为 ECC一种建立公开密钥加密的算法基于椭圆曲线数学。 ECC的主要优势是在某些情况下它比其他的方法使用更小的密钥——比如RSA加密算法——提供相当的或更高等级的安全。ECC的另一个优势是可以定义群之间的双线性映射基于Weil对或是Tate对双线性映射已经在密码学中发现了大量的应用例如基于身份的加密。其缺点是同长度密钥下加密和解密操作的实现比其他机制花费的时间长 [1] 但由于可以使用更短的密钥达到同级的安全程度所以同级安全程度下速度相对更快。一般认为160比特的椭圆曲线密钥提供的安全强度与1024比特RSA密钥相当。 关键总结 设私钥、公钥分别为k、K即K kG其中G为G点。 公钥加密 选择随机数r将消息M生成密文C该密文是一个点对即 C {rG, MrK}其中K为公钥 私钥解密 M rK - k(rG) M r(kG) - k(rG) M 其中k、K分别为私钥、公钥。 题目样式举例 ECC脚本积累(解出最后的公钥和私钥即可) import collections import random EllipticCurve collections.namedtuple(EllipticCurve, name p a b g n h) curve EllipticCurve( secp256k1, # Field characteristic. pint(input(p)), # Curve coefficients. aint(input(a)), bint(input(b)), # Base point. g(int(input(Gx)), int(input(Gy))), # Subgroup order. nint(input(k)), # Subgroup cofactor. h1, ) # Modular arithmetic ########################################################## def inverse_mod(k, p): Returns the inverse of k modulo p. This function returns the only integer x such that (x * k) % p 1. k must be non-zero and p must be a prime. if k 0: raise ZeroDivisionError(division by zero) if k 0: # k ** -1 p - (-k) ** -1 (mod p) return p - inverse_mod(-k, p) # Extended Euclidean algorithm. s, old_s 0, 1 t, old_t 1, 0 r, old_r p, k while r ! 0: quotient old_r // r old_r, r r, old_r - quotient * r old_s, s s, old_s - quotient * s old_t, t t, old_t - quotient * t gcd, x, y old_r, old_s, old_t assert gcd 1 assert (k * x) % p 1 return x % p # Functions that work on curve points ######################################### def is_on_curve(point): Returns True if the given point lies on the elliptic curve. if point is None: # None represents the point at infinity. return True x, y point return (y * y - x * x * x - curve.a * x - curve.b) % curve.p 0 def point_neg(point): Returns -point. assert is_on_curve(point) if point is None: # -0 0 return None x, y point result (x, -y % curve.p) assert is_on_curve(result) return result def point_add(point1, point2): Returns the result of point1 point2 according to the group law. assert is_on_curve(point1) assert is_on_curve(point2) if point1 is None: # 0 point2 point2 return point2 if point2 is None: # point1 0 point1 return point1 x1, y1 point1 x2, y2 point2 if x1 x2 and y1 ! y2: # point1 (-point1) 0 return None if x1 x2: # This is the case point1 point2. m (3 * x1 * x1 curve.a) * inverse_mod(2 * y1, curve.p) else: # This is the case point1 ! point2. m (y1 - y2) * inverse_mod(x1 - x2, curve.p) x3 m * m - x1 - x2 y3 y1 m * (x3 - x1) result (x3 % curve.p, -y3 % curve.p) assert is_on_curve(result) return result def scalar_mult(k, point): Returns k * point computed using the double and point_add algorithm. assert is_on_curve(point) if k 0: # k * point -k * (-point) return scalar_mult(-k, point_neg(point)) result None addend point while k: if k 1: # Add. result point_add(result, addend) # Double. addend point_add(addend, addend) k 1 assert is_on_curve(result) return result # Keypair generation and ECDHE ################################################ def make_keypair(): Generates a random private-public key pair. private_key curve.n public_key scalar_mult(private_key, curve.g) return private_key, public_key private_key, public_key make_keypair() print(private key:, hex(private_key)) print(public key: (0x{:x}, 0x{:x}).format(*public_key))
http://www.dnsts.com.cn/news/216711.html

相关文章:

  • nodejs做网站的弊端中国菲律宾友谊
  • 济南网站建设大标网络全包家装原创装修网站
  • 中英文切换网站模板有没有做武棍的网站
  • 佛山设计网站设计价格网站前端制作费用
  • 专业外贸网站制作价格网站建设管理职责
  • 查网站备案号玫瑰在线 网站建设内容
  • 网上销售推广方案seo快速排名上首页
  • 重庆建站服务商dede网站 远程生成
  • 网站做支付需要准备什么东西征婚网站咋做
  • 做片头片尾比较好的网站营销型网站建设公司
  • 重庆市建设工程信息网站宝丰网站制作公司
  • 做外贸网站要什么条件wordpress如何生成单页的网站地图
  • 信用网站建设意见搜索引擎营销sem包括
  • 网站 模板下载株洲网站建设服务
  • 长治网站建设招聘深圳做关键词优化平台
  • 做网站被骗该咋样做广告关键词排名
  • 招聘网站建设人员的要求商城火车站
  • 深圳专业医疗网站建设汕头发展
  • 网站地图制作软件柳州市城乡建设局网站
  • 大型网站开发 赚钱潜江网站建设
  • 最新聊天记录做图网站网站百度不到
  • 做网站用哪个ecalipse广西建设网站网址多少钱
  • 商用高端网站设计新感觉建站wordpress怎么开启下载收费功能
  • 怎么做网站论坛整站优化推广
  • 书法网站开发的前景网络需求分析的主要内容有哪些
  • win10 做网站服务器吗成都装饰网站建设
  • 公司想推广做网站有用做视频网站要注意什么
  • 上城区商城网站建设南宁seo外包服务
  • 怎么样制作网站教程网站动态交互
  • 建设音乐网站功能定位低代码建站平台