-
-
[原创]2021 KCTF 春季赛 第二题 南冥神功
-
2021-5-11 16:05 4116
-
反编译
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 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | sub_40AD70(); sub_4AF840(( int )&dword_4B8860, "Input your code: " ); sub_4B0AB0(( int )&dword_4B8680, ipt); if ( strlen(ipt) < = 48 ) { p = ipt[ 0 ]; if ( ipt[ 0 ] ) { ii = 0 ; yy = 0 ; xx_ = 0 ; is36 = ::is36; is0 = c0_z[ 0 ]; LOOP: if ( is36 > 0 ) { jj = 0 ; if ( is0 = = p ) { LABEL_11: v7 = (ii + jj / 6 ) % 6 ; ii_jj = jj + ii; xx = xx_; sw2 = v7; sw = 5 - ii_jj % 6 ; for ( i = 0 ; ; i = 1 ) { switch ( sw ) { case 1 : + + xx; break ; case 2 : v17 = (yy + + & 1 ) = = 0 ; / / 当前y是偶数则 / / x + + y + + / / 否则 y + + xx + = v17; break ; case 3 : v12 = (yy + + & 1 ) ! = 0 ; / / 当前y是奇数则 / / x - - y + + / / 否则 y + + xx - = v12; break ; case 4 : - - xx; break ; case 5 : v19 = (yy - - & 1 ) ! = 0 ; / / 当前y是奇数则 / / x - - y - - / / 否则 y - - xx - = v19; break ; default: v18 = (yy - - & 1 ) = = 0 ; / / 当前y是偶数数则 / / x + + y - - / / 否则 y - - xx + = v18; break ; } if ( xx > 9 ) break ; if ( yy > 8 ) break ; v13 = &pz[yy][xx]; / / 一定要为 0 if ( * v13 ) break ; * v13 = 1 ; if ( i = = 1 ) { + + ii; xx_ = xx; p = ipt[ii]; if ( p ) goto LOOP; goto END; } sw = sw2; } } else { while ( is36 ! = + + jj ) { if ( c0_z[jj] = = p ) goto LABEL_11; } } } } else { END: tst = pz; cc = 0 ; do { v16 = tst + 1 ; / / tst 90 个都为 1 do { cc + = * (_BYTE * )tst = = 0 ; tst = (char ( * )[ 10 ])((char * )tst + 1 ); } while ( v16 ! = tst ); } while ( &pz_end ! = (_UNKNOWN * )v16 ); if ( !cc ) { sub_4ABF30(&dword_4B8860, "Good job!" , 9 ); sub_4AD980(&dword_4B8860); return 0 ; } } } sub_4ABF30(&dword_4B8860, "Try again..." , 12 ); sub_4AD980(&dword_4B8860); |
流程
- 有个 9*10 迷宫
S 为起点,左边标记了0为偶数行,1为奇数行,目的是不能碰到1的走过所有01234567890
: S010010011
1
:
1100100100
0
:
0010111110
1
:
0110100100
0
:
0010010011
1
:
1101110101
0
:
0011110101
1
:
0110010101
0
:
0001001100
- 读入长度小于48字节的字符 ipt
- 令 i 为 ipt 下标,从 0 开始
- 令 j 为 ipt[i] 在 0-9A-Z 的序号
- 令 a = 5 - (i + j) % 6,b = (i + j/6) % 6,a、b 为运动连续两步运动
- 运动方向对应图
括号内是行动所在行的限定123↖
5
(
1
行) ↑
0
(
1
行)
/
5
(
0
行) ↗
0
(
0
行)
←
4
→
1
↙
3
(
1
行) ↓
2
(
1
行)
/
3
(
0
行) ↘
2
(
0
行)
解法
- 先人肉出运动描述:
1234321234321101210050543450501210121234322321
,推测出输入有23位
代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | r = "1234321234321101210050543450501210121234322321" z = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" s = "" for i in xrange ( 23 ): a = ord (r[i * 2 ]) - ord ( '0' ) b = ord (r[i * 2 + 1 ]) - ord ( '0' ) t = False for j in xrange ( 36 ): if a = = 5 - (i + j) % 6 and b = = (i + j / 6 ) % 6 : assert not t # 测试唯一解 t = True s + = z[j] print s |
赞赏
他的文章
看原图