-
-
[原创]KCTF2022 第二题pizzatqqql队题解
-
2022-5-12 16:18 5387
-
KCTF2022 第二题题解
解题
第一部分
输入一段字符串,然后用输入的字符串在下图进行一系列运算后,将运算的结果存入v39之中,然后进行一个sbox的初始化,和输入没有半毛钱关系,每次运行都是相同的数,所以可以动调然后取出。
接着用sbox和我们的输入进行了一系列运算,将结果存进int类型的v11中。
接下来是一个常规的字符串转数字存入内存的函数,不过这里的ascii大于0x39的字符是减55后存入内存。
然后下图的最下面的if判断需要满足,否则game over。向上看do while,发现和我们的输入有关的只有v39,也就是上面的那个运算的结果
这里通过爆破得出了v17的范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | #include <cstring> #include <iostream> using namespace std; int v3; / / ebx int len ; / / esi char v5; / / cl int v6; / / edi char * v7; / / esi char v8; / / ch char v9; / / cl char v10; / / dl int v11; / / ecx int i; / / edx int v13; / / ecx int v14; / / esi int v15; / / eax int j; / / edx int v17; / / edi int v18; / / esi int v19; / / edi int v20; / / esi int v21; / / eax int v22; / / ecx int v23; / / eax int v24; / / ecx int v25; / / eax int v26; / / edx int v27; / / ecx char v28; / / bl char v29; / / bh int v30; / / ecx char * v31; / / edi int v33[ 200 ]; / / [esp + 10h ] [ebp - 368h ] int v34; / / [esp + 330h ] [ebp - 48h ] int v35; / / [esp + 334h ] [ebp - 44h ] int v36; / / [esp + 338h ] [ebp - 40h ] int v37; / / [esp + 33Ch ] [ebp - 3Ch ] int v38; / / [esp + 340h ] [ebp - 38h ] char v39; / / [esp + 347h ] [ebp - 31h ] char input [ 6 ]; / / [esp + 348h ] [ebp - 30h ] BYREF char v41[ 38 ]; / / [esp + 34Eh ] [ebp - 2Ah ] BYREF int main() { for ( int i = 0 ; i < = 0xff ; i + + ) { v13 = i; v15 = v13; for (j = 1 ; j < 200 ; + + j) { if ((v15 & 1 ) ! = 0 ) / / 奇数 * 3 + 1 v15 = 3 * v15 + 1 ; else v15 >> = 1 ; / / 偶数右移 1 v33[j] = v15; } v17 = v33[ 198 ] | v33[ 197 ] | v33[ 196 ]; cout << v17 << endl; } } |
只有7,这就好办了。爆破input前三个数就行。这里注意此处的input已经被之前的string_into_memory函数转化过了,爆破固定的范围即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | #include <cstring> #include <iostream> using namespace std; int v3; / / ebx int len ; / / esi char v5; / / cl int v6; / / edi char * v7; / / esi char v8; / / ch char v9; / / cl char v10; / / dl int v11; / / ecx int i; / / edx int v13; / / ecx int v14; / / esi int v15; / / eax int j; / / edx int v17; / / edi int v18; / / esi int v19; / / edi int v20; / / esi int v21; / / eax int v22; / / ecx int v23; / / eax int v24; / / ecx int v25; / / eax int v26; / / edx int v27; / / ecx char v28; / / bl char v29; / / bh int v30; / / ecx char * v31; / / edi int v33[ 200 ]; / / [esp + 10h ] [ebp - 368h ] int v34; / / [esp + 330h ] [ebp - 48h ] int v35; / / [esp + 334h ] [ebp - 44h ] int v36; / / [esp + 338h ] [ebp - 40h ] int v37; / / [esp + 33Ch ] [ebp - 3Ch ] int v38; / / [esp + 340h ] [ebp - 38h ] char v39; / / [esp + 347h ] [ebp - 31h ] char input [ 6 ]; / / [esp + 348h ] [ebp - 30h ] BYREF char v41[ 38 ]; / / [esp + 34Eh ] [ebp - 2Ah ] BYREF int main() { for ( int j = 0 ; j < 50 ; j + + ) { for ( int z = 0 ; z < 50 ; z + + ) { for ( int w = 0 ; w < 50 ; w + + ) { if ((j ^ z ^ w) = = 7 ) { if (j > 9 ) { cout << (char)(j + 55 ); } else { cout << (char)(j + 48 ); } if (z > 9 ) { cout << (char)(z + 55 ); } else { cout << (char)(z + 48 ); } if (w > 9 ) { cout << (char)(w + 55 ); } else { cout << (char)(w + 48 ); } cout << endl; } } } } } |
得出一堆满足的数,随便选一个0AD填进去第一关就过了
第二部分
这里相当于告诉你后面几位是多少了,不做赘述,加上后现在已知的flag是0ADKCTF
第三部分
又是一个运算
v19是v17+2,v17就是刚刚爆破出来结果全是7的那个,所以可以得知循环的次数固定是9次。此处进行运算的是我们输入的0ADKCTF的后九位。假设输入为0ADKCTF123456789时,这里的v41[v22]最开始指向的就是1
当v24%v36不等于0时会失败。注意这里循环一次只需要取一次余,不用将前面的余全部取一遍。
比如输入123456789,先判断1%1==0,然后判断12%2==0,然后判断123%3==0,依次类推。
写了个脚本爆破,但是发现后面还有个限制,这里是从小到大排序我们刚刚输入的九个数
然后这里是比较,必须1到9全部出现。所以刚刚的爆破还要加个限制。
脚本如下
1 2 3 4 5 | for i in range ( 100000000 , 1000000000 ): if i / / 10000000 % 2 = = 0 and i / / 1000000 % 3 = = 0 and i / / 100000 % 4 = = 0 and i / / 10000 % 5 = = 0 and i / / 1000 % 6 = = 0 and i / / 100 % 7 = = 0 and i / / 10 % 8 = = 0 and i % 9 = = 0 : num_all = str (i) if "1" in num_all and "2" in num_all and "3" in num_all and "4" in num_all and "5" in num_all and "6" in num_all and "7" in num_all and "8" in num_all and "9" in num_all : print (i) |
发现只能爆破出一个数381654729
第四部分
这个函数不知道有啥用,我直接f8发现没事就没看了
最后一关就是要满足这个v34等于这个数,查看v34交叉引用,发现是和很上面的sbox运算有关
我们的前三位爆破出了很多数,我是随便选了一个就过的,看来这里是作为前三位的限制。
因为我们只有前三位不是唯一的,只需要爆破前三位就行。脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | #include <iostream> using namespace std; int v3; / / ebx int len ; / / esi char v5; / / cl int v6; / / edi char * v7; / / esi char v8; / / ch char v9; / / cl char v10; / / dl int v11; / / ecx int i; / / edx int v13; / / ecx int v14; / / esi int v15; / / eax int j; / / edx int v17; / / edi int v18; / / esi int v19; / / edi int v20; / / esi int v21; / / eax int v22; / / ecx int v23; / / eax int v24; / / ecx int v25; / / eax int v26; / / edx int v27; / / ecx char v28; / / bl char v29; / / bh int v30; / / ecx char * v31; / / edi int v33[ 200 ]; / / [esp + 10h ] [ebp - 368h ] int v34; / / [esp + 330h ] [ebp - 48h ] int v35; / / [esp + 334h ] [ebp - 44h ] int v36; / / [esp + 338h ] [ebp - 40h ] int v37; / / [esp + 33Ch ] [ebp - 3Ch ] int v38; / / [esp + 340h ] [ebp - 38h ] char v39; / / [esp + 347h ] [ebp - 31h ] char v41[ 38 ]; / / [esp + 34Eh ] [ebp - 2Ah ] BYREF unsigned int sbox[] = { 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 }; char input [] = "0ADKCTF381654729" ; int main() { int duibi = 0xad1f89a ; v11 = - 1 ; for ( int j1 = 0 ; j1 < 0x7f ; j1 + + ) { for ( int j2 = 0 ; j2 < 0x7f ; j2 + + ) { for ( int j3 = 0 ; j3 < 0x7f ; j3 + + ) { v11 = - 1 ; v11 = sbox[(unsigned __int8)(v11 ^ j1)] ^ (v11 >> 8 ); v11 = sbox[(unsigned __int8)(v11 ^ j2)] ^ (v11 >> 8 ); v11 = sbox[(unsigned __int8)(v11 ^ j3)] ^ (v11 >> 8 ); for (i = 3 ; i < 16 ; + + i) v11 = sbox[(unsigned __int8)(v11 ^ input [i])] ^ (v11 >> 8 ); if (v11 = = duibi) cout << char(j1) << char(j2) << char(j3) << endl; } } } } |
得到前三位是421,所以最终的序列号是421KCTF381654729
感想
题出的很有意思,像闯关游戏一样hhh
然后和第一名差了2秒,有点悲伤(
【看雪培训】目录重大更新!《安卓高级研修班》2022年春季班开始招生!