看雪2022 KCTF 春季赛 | 第二题设计思路及解析(含视频)
出题团队简介


赛题设计思路
题目描述
帮小学小朋友看奥数的时候看到的,觉得很有意思就出题了,然后加了一些回忆杀在里面(砍传奇啊)
如果这个数是奇数,则把它扩大到原来的 3 倍后再加 1 。
用 1 到 9 组成一个九位数,//每个数字都用了一次
使得这个数的第一位能被 1 整除,
前两位组成的两位数能被 2 整除,前三位组成的三位数能被 3 整除,
以此类推,一直到整个九位数能被 9 整除。
381654729 是唯一一个满足要求的数!
赛题解析
本赛题解析由看雪论坛 htg 给出:

工具:IDA
分析步骤:先简略看看程序运行情况
1、找关键代码
查阅字符串方法,View->Strings,搜索
找 main 方法:
_main 按F5即可转换伪代码
2、显示中文字符串
如果没有 GBK ,那么点开之后,按住 insert 即可弹出一个新的对话框,直接输入 GBK。
设置完成之后,在 View->Strings 里 右键 Rebuild 对字符串进行重新搜索建立。
如果还是没有,那么关闭IDA,再打开IDA,重新来一遍
3、分析主函数结构
sub_EB100C(
"%s\n 而你,作为一个操控韩立的人,千万不要让韩立 GAME OVER 了.\n现在,输入你的操作ID吧
asc_EB55C0);
sub_EB103A("%s", Arglist);【获取用户输入,此处经过测算,长度<= 0x1E 即 30 位,查看局部变量表】
sub_EB100C("\n现在,你就是韩立,韩立就是你,如遇绝境,吼:男人至死是少年!");
v41 = 0;
lenSN = strlen(Arglist);
SN构造一个 resultA (一个字节)
resultA = 0;if ( lenSN ){v7 = Arglist;do{v5 ^= *v7;--v6;++v7;v8 = 8;do{v9 = 2 * v5;v10 = v9 ^ 7;if ( v9 >= 0 )v10 = v9;v5 = v10;--v8;}while ( v8 );}while ( v6 );lenSN = lenSNcopy;resultA = v10; // resultA是输出的结果}
initArrayA(); // 构造:dword_EB5B20 数组。这个是全局变量,与用户输入无关v11 = -1;for ( i = 0; i < lenSN; ++i )v11 = arrayA[(unsigned __int8)(v11 ^ Arglist[i])] ^ (v11 >> 8);// 0x0AD1F89AsignA = ~v11; // signA == 0xF52E0765
stringToInt((int)Arglist, lenSN); // 对用户输入的字符串进行转换:将字符转换成数值,'0123456789ABCDEF'-->0123456789ABCDEF
v13 = resultA;v36 = 1;v35 = resultA + 1;v14 = v35;do{v15 = v13;for ( j = 1; j < 0xC8; ++j ){if ( (v15 & 1) != 0 )v15 = 3 * v15 + 1;elsev15 >>= 1;arrayB[j] = v15;}++v13;}while ( v13 < v14 ); // 只循环一遍,构造了v33表signB = arrayB[0xC6] | arrayB[0xC5] | arrayB[0xC4];// 1^2^4=7lenSNcopy2 = lenSNcopy;if ( signB != (Arglist[2] ^ Arglist[1] ^ Arglist[0]) )// 第一个判断:前三位异或之后结果为7
midBytes = signB + 2;restBytes = lenSNcopy2 - midBytes - 7;
if ( Arglist[3] != 0x14 )if ( Arglist[4] != 0xC )if ( Arglist[5] != 0x1D )if ( Arglist[6] != 0xF )
v21 = 0;lenSNcopy = 0;if ( midBytes > 0 ){v22 = 1;do{v23 = Arglist[v22 + 6] + 10 * v37; // 十进制算法。十进制数值字符串转换成十进制数值??v24 = v23 - 0x37373737; // 7777if ( v23 <= 0x4B435445 ) // KCTEv24 = v23;v37 = v24;if ( v24 % v36 ) // 不能跳进去:需要被整除。goto LABEL_50;v21 = lenSNcopy + 1;v22 = v36 + 1;lenSNcopy = v21;++v36;}while ( v21 < midBytes );}
v25 = midBytes - 1;if ( midBytes - 1 > 0 ) // 冒泡排序算法:Arglist【7:7+signBsubTwo-1】即对从7开始的signBsubTwo个数进行排序{v26 = midBytes - 1;do{v27 = 0;if ( v25 > 0 ){do{v28 = Arglist[v27 + 7];v29 = Arglist[v27 + 8];if ( v28 > v29 ){Arglist[v27 + 7] = v29;Arglist[v27 + 8] = v28;}++v27;}while ( v27 < v25 );v3 = 0;}--v25;--v26;}while ( v26 );}
stringToInt((int)a1234567890Abcd, midBytes); // 1234567890_ABCDEFGHIJKLMNOPQRSTUVWXYZ转换成1234567890,0x28,abcdef,0x16,0x17,0x18,......,0x23
v30 = 0;if ( midBytes > 0 ){while ( a1234567890Abcd[v30] == Arglist[v30 + 7] )// 第六个判断:必须满足{if ( ++v30 >= midBytes ) // 必须跳出去:重复次数是 signBsubTwogoto LABEL_41;}goto LABEL_49;}
Arglist7laterTrans = &Arglist[midBytes + 7];sub_EB10E1((int)Arglist7laterTrans, restBytes);if ( restBytes <= 0 ) // 第七个判断
if ( restBytes <= 0 ) // 第七个判断{LABEL_45:sub_EB100C("\n你想吃猪肉,到猪洞七层准备打个白野猪.白野猪死后尸体尽然掉出一把 屠龙 .");if ( signA == 0xF52E0765 ) // 第八个判断……………………}else{ // 这是一个大坑,没必要进入while ( ((unsigned __int8)asc_EB55C0[v3] ^ (unsigned __int8)Arglist7laterTrans[v3]) == asc_EB3DC8[v3] ){if ( ++v3 >= restBytes )goto LABEL_45;………………}}
4、编写Python代码
详见下面内容
import os#从IDA里拷贝出来【如有时间,再考虑具体算法】#初始化大数组def InitArrayA():#先直接从 IDA 里拷贝。tmpArray = [ 0x00000000,0x09073096,0x120E612C,0x1B0951BA,0xFF6DC419,0xF66AF48F,0xED63A535,0xE46495A3,0xFEDB8832,0xF7DCB8A4,0xECD5E91E,0xE5D2D988,0x01B64C2B,0x08B17CBD,0x13B82D07,0x1ABF1D91,0xFDB71064,0xF4B020F2,0xEFB97148,0xE6BE41DE,0x02DAD47D,0x0BDDE4EB,0x10D4B551,0x19D385C7,0x036C9856,0x0A6BA8C0,0x1162F97A,0x1865C9EC,0xFC015C4F,0xF5066CD9,0xEE0F3D63,0xE7080DF5,0xFB6E20C8,0xF269105E,0xE96041E4,0xE0677172,0x0403E4D1,0x0D04D447,0x160D85FD,0x1F0AB56B,0x05B5A8FA,0x0CB2986C,0x17BBC9D6,0x1EBCF940,0xFAD86CE3,0xF3DF5C75,0xE8D60DCF,0xE1D13D59,0x06D930AC,0x0FDE003A,0x14D75180,0x1DD06116,0xF9B4F4B5,0xF0B3C423,0xEBBA9599,0xE2BDA50F,0xF802B89E,0xF1058808,0xEA0CD9B2,0xE30BE924,0x076F7C87,0x0E684C11,0x15611DAB,0x1C662D3D,0xF6DC4190,0xFFDB7106,0xE4D220BC,0xEDD5102A,0x09B18589,0x00B6B51F,0x1BBFE4A5,0x12B8D433,0x0807C9A2,0x0100F934,0x1A09A88E,0x130E9818,0xF76A0DBB,0xFE6D3D2D,0xE5646C97,0xEC635C01,0x0B6B51F4,0x026C6162,0x196530D8,0x1062004E,0xF40695ED,0xFD01A57B,0xE608F4C1,0xEF0FC457,0xF5B0D9C6,0xFCB7E950,0xE7BEB8EA,0xEEB9887C,0x0ADD1DDF,0x03DA2D49,0x18D37CF3,0x11D44C65,0x0DB26158,0x04B551CE,0x1FBC0074,0x16BB30E2,0xF2DFA541,0xFBD895D7,0xE0D1C46D,0xE9D6F4FB,0xF369E96A,0xFA6ED9FC,0xE1678846,0xE860B8D0,0x0C042D73,0x05031DE5,0x1E0A4C5F,0x170D7CC9,0xF005713C,0xF90241AA,0xE20B1010,0xEB0C2086,0x0F68B525,0x066F85B3,0x1D66D409,0x1461E49F,0x0EDEF90E,0x07D9C998,0x1CD09822,0x15D7A8B4,0xF1B33D17,0xF8B40D81,0xE3BD5C3B,0xEABA6CAD,0xEDB88320,0xE4BFB3B6,0xFFB6E20C,0xF6B1D29A,0x12D54739,0x1BD277AF,0x00DB2615,0x09DC1683,0x13630B12,0x1A643B84,0x016D6A3E,0x086A5AA8,0xEC0ECF0B,0xE509FF9D,0xFE00AE27,0xF7079EB1,0x100F9344,0x1908A3D2,0x0201F268,0x0B06C2FE,0xEF62575D,0xE66567CB,0xFD6C3671,0xF46B06E7,0xEED41B76,0xE7D32BE0,0xFCDA7A5A,0xF5DD4ACC,0x11B9DF6F,0x18BEEFF9,0x03B7BE43,0x0AB08ED5,0x16D6A3E8,0x1FD1937E,0x04D8C2C4,0x0DDFF252,0xE9BB67F1,0xE0BC5767,0xFBB506DD,0xF2B2364B,0xE80D2BDA,0xE10A1B4C,0xFA034AF6,0xF3047A60,0x1760EFC3,0x1E67DF55,0x056E8EEF,0x0C69BE79,0xEB61B38C,0xE266831A,0xF96FD2A0,0xF068E236,0x140C7795,0x1D0B4703,0x060216B9,0x0F05262F,0x15BA3BBE,0x1CBD0B28,0x07B45A92,0x0EB36A04,0xEAD7FFA7,0xE3D0CF31,0xF8D99E8B,0xF1DEAE1D,0x1B64C2B0,0x1263F226,0x096AA39C,0x006D930A,0xE40906A9,0xED0E363F,0xF6076785,0xFF005713,0xE5BF4A82,0xECB87A14,0xF7B12BAE,0xFEB61B38,0x1AD28E9B,0x13D5BE0D,0x08DCEFB7,0x01DBDF21,0xE6D3D2D4,0xEFD4E242,0xF4DDB3F8,0xFDDA836E,0x19BE16CD,0x10B9265B,0x0BB077E1,0x02B74777,0x18085AE6,0x110F6A70,0x0A063BCA,0x03010B5C,0xE7659EFF,0xEE62AE69,0xF56BFFD3,0xFC6CCF45,0xE00AE278,0xE90DD2EE,0xF2048354,0xFB03B3C2,0x1F672661,0x166016F7,0x0D69474D,0x046E77DB,0x1ED16A4A,0x17D65ADC,0x0CDF0B66,0x05D83BF0,0xE1BCAE53,0xE8BB9EC5,0xF3B2CF7F,0xFAB5FFE9,0x1DBDF21C,0x14BAC28A,0x0FB39330,0x06B4A3A6,0xE2D03605,0xEBD70693,0xF0DE5729,0xF9D967BF,0xE3667A2E,0xEA614AB8,0xF1681B02,0xF86F2B94,0x1C0BBE37,0x150C8EA1,0x0E05DF1B,0x0702EF8D ]return tmpArray#根据输入的SN,获取resultAdef CalcResultA(SN):initByte = 0x00tmpByteA = 0x00tmpByteB = 0x00for ch in SN:#print("ch:{}".format(ch))initByte ^= ord(ch)for i in range(8):tmpByteA = (2 * initByte) & 0xFF#print("tmpByteA:{}".format(hex(tmpByteA)[2:]))tmpByteB = tmpByteA ^ 7if tmpByteA < 0x80 : #对应于 正数tmpByteB = tmpByteAinitByte = tmpByteB#print("tmpByteB:{}".format(hex(tmpByteB)[2:]))return tmpByteB#对输入的字符进行处理:'0'->0 '9'--->9 'a'---->10 ....def String2IntList(SN):returnList =[]for ch in SN:tmpBase = 0x30if ord(ch)>=0x3A:tmpBase = 0x37returnList.append(ord(ch)-tmpBase)return returnList#搜索函数def DoSearch(SN):global arrayA#print("当前的SN:{}\n 长度:{}".format(SN,len(SN)))#os.system("pause")#TODO:已经构造完成:开始进行判断resultA = CalcResultA(SN)#print("resultA:{}".format(hex(resultA)))signA = 0xFFFFFFFFlenSN = len(SN)for ch in SN:tmpIndex = (signA ^ ord(ch)) & 0xFFtmpValue = arrayA[tmpIndex]#print("tmpIndex:{}".format(hex(tmpIndex)))#SAR算数移位if signA >= 0x80000000:#负数,右移之后,要在最高位带上FFsignA = ((signA >> 8)|0xFF000000) ^ tmpValueelse:signA = (signA >> 8) ^ tmpValue#print("signA:{}".format(hex(signA)))signA = signA ^ 0xFFFFFFFF #取反 就是 异或 全1if signA != 0xF52E0765:#print("signA: {} != 0xF52E0765".format(hex(signA)))#os.system("pause")return None#输出一个结果:print("找到SN:{}".format(SN))os.system("pause")#主函数入口def main():#序列号SN = ""#分析算法结构'''01 3个字符02 4个固定字符,即为 KCTF03 不大于9个字符,且必须为数值1-904 没有字符,题目埋了一个坑'''#第3部分:9个字符。part3Code = "381654729"for a in usedList:for b in usedList:for c in usedList:SN = chr(a) + chr(b) + chr(c)#对SN:前3个字符进行计算,以确保其相互异或,结果为 7tmpIntLst = String2IntList(SN)if tmpIntLst[0] ^ tmpIntLst[1] ^ tmpIntLst[2] != 0x7:continue#print("找到SN:{}".format(SN))#前单个字符要进行sign换算SN = SN +'KCTF' + part3Code#调用另外一个命令,继续构造DoSearch(SN)if __name__ == "__main__":global arrayAarrayA=[]usedList = list(range(0x21,0x7E,1))print("usedCharList:\n{}".format([hex(x)[2:].upper() for x in usedList]))arrayA = InitArrayA()#main()'''以下是辅助代码constStr = '1234567890_ABCDEFGHIJKLMNOPQRSTUVWXYZ'constIntList = String2IntList(constStr)print("constIntList")print(','.join(hex(x)[2:] for x in constIntList))print('测试最后的部分')asc_EB55C0 = '我,韩立,作为一名光荣的程序员,月亮不睡我不睡,太阳没起我就起,夜以继日,终于把肉身修炼腐朽了...然后,穿越了...'asc_EB3DC8 = '我辈读书人一生所求不过四事:为天地立心,为生民立命,为往圣继绝学,为万世开太平.'asc_EB55C0_to_gbk = asc_EB55C0.encode("gbk")asc_EB3DC8_to_gbk = asc_EB3DC8.encode("gbk")returnRestList = []for i in range(20):returnRestList.append(asc_EB55C0_to_gbk[i]^asc_EB3DC8_to_gbk[i])print("returnRestList")print(','.join(hex(x)[2:] for x in returnRestList))#0,0,9d,8,1d,0,68,c5,1f,3c,1c,11,1b,41,8,2,7e,11,7a,62'''
###找到满足要求的数值:9import itertoolsfrom itertools import permutations'''num_list = [1,2,3,4,5,6,7,8,9]num_list = [1,2,3,4,5,6,7,8]num_list = [1,2,3,4,5,6,7] #nonenum_list = [1,2,3,4,5,6]num_list = [1,2,3,4,5] #nonenum_list = [1,2,3,4]#nonenum_list = [1,2,3]num_list = [1,2]num_list = [1]'''def permute(nums):result = []for i in permutations(nums,len(nums)):#print(list(i))tmp = "".join(str(x) for x in list(i))#print("tmp:{}".format(tmp))result.append(tmp)return resultdef main():#print('\n')#print(permute(num_list))for i in range(9):num_list = []##生成 num_listfor j in range(i+1):num_list.append(j+1)print("#"*50+"\n"+"num_list:{}".format(num_list))##num_list 生成 permute(num_list) 用作候选lst = permute(num_list)##开始查找cur = len(num_list)for k in lst:for m in range(cur):n = m + 1x = int(k[:n])if x % n != 0:breakif n == cur:print("found:\t{}".format(k))if __name__ == "__main__":print("开始查找")main()print("#"*50)'''found:381654729found:38165472found:123654found:321654found:123found:321found:12found:1'''


第三题《石像病毒》还在火热进行中,
[广告]赞助链接:
关注数据与安全,洞悉企业级服务市场:https://www.ijiandao.com/
让资讯触达的更精准有趣:https://www.0xu.cn/
关注KnowSafe微信公众号随时掌握互联网精彩
- 你的耳机在被偷听?多款音频设备曝出漏洞:索尼、Bose等
- Duplicati 一款免费、开源的备份工具
- 火狐浏览器v137.0正式版内置的本地机器翻译技术带来简体中文的支持
- 今日宜炫“父”
- 国密证书 VS 传统 SSL 证书,到底区别在哪?
- 微信春节大数据出炉:《三体》阅读量第一 ;曝iOS 17应用商店将向第三方开放;斯坦福大学推出DetectGPT|极客头条
- 勒索软件团伙在攻击警察局后主动提供解密器
- CVE-2021-1732 Microsoft Windows10 本地提权漏 研究及Exploit开发
- Facebook、Signal、Google聊天应用程序曝漏洞,音频视频数据恐被监听
- 读懂本文,网安厂商市场经费不再白花
- 小米路由器AX6000:Wi-Fi 6增强版,极速升级
- 云时代下,移动云揭秘数据库“新解”
赞助链接



