-
-
[原创]2021 KCTF 秋季赛 第二题 迷失丛林
-
2021-11-17 11:53 9693
-
基本流程
windows 程序通过查找 GetDlgItemTextA 引用找到关键入口
流程如下:
- 获取输入的 32 个字符,转换成 16字节
ipt
(大写HEX,注意和输入的内容有 swap8 的差异) - 把
ipt
分半为ipt1
,ipt2
- 将
ipt1
拷贝进内置的tb
(256表)前 8 字节 - 用 第一个算法 验证
tb
- 通过 第二个算法 变换
tb
- 通过 第三个算法 运算
ipt2
、tb
得到的结果 对比 GoodJob~
切入点
通过 第二个算法 有对换的特点,和 原始tb 唯一数字的特点
可以看出 tb
应该要满足 256 数字唯一
解题流程
- 找到丢失的 8 个字节
loss
- 枚举所有
pad
可能,找到能够过 第一个算法 的排列part1
- 随便输入 part1 + 16 字符,dump 第二个算法 之后的
tb
- 直接爆破 第三个算法 得到
part2
代码
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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 | package main import ( "fmt" ) / / tb 404000 var t2tb = []byte{ 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0xA2 , 0x9B , 0xF4 , 0xDF , 0xAC , 0x7C , 0xA1 , 0xC6 , 0x16 , 0xD0 , 0x0F , 0xDD , 0xDC , 0x73 , 0xC5 , 0x6B , 0xD1 , 0x96 , 0x47 , 0xC2 , 0x26 , 0x67 , 0x4E , 0x41 , 0x82 , 0x20 , 0x56 , 0x9A , 0x6E , 0x33 , 0x92 , 0x88 , 0x29 , 0xB5 , 0xB4 , 0x71 , 0xA9 , 0xCE , 0xC3 , 0x34 , 0x50 , 0x59 , 0xBF , 0x2D , 0x57 , 0x22 , 0xA6 , 0x30 , 0x04 , 0xB2 , 0xCD , 0x36 , 0xD5 , 0x68 , 0x4D , 0x5B , 0x45 , 0x9E , 0x85 , 0xCF , 0x9D , 0xCC , 0x61 , 0x78 , 0x32 , 0x76 , 0x31 , 0xE3 , 0x80 , 0xAD , 0x39 , 0x4F , 0xFA , 0x72 , 0x83 , 0x4C , 0x86 , 0x60 , 0xB7 , 0xD7 , 0x63 , 0x0C , 0x44 , 0x35 , 0xB3 , 0x7B , 0x19 , 0xD4 , 0x69 , 0x08 , 0x0B , 0x1F , 0x3D , 0x11 , 0x79 , 0xD3 , 0xEE , 0x93 , 0x42 , 0xDE , 0x23 , 0x3B , 0x5D , 0x8D , 0xA5 , 0x77 , 0x5F , 0x58 , 0xDB , 0x97 , 0xF6 , 0x7A , 0x18 , 0x52 , 0x15 , 0x74 , 0x25 , 0x62 , 0x2C , 0x05 , 0xE8 , 0x0D , 0x98 , 0x2A , 0x43 , 0xE2 , 0xEF , 0x48 , 0x87 , 0x49 , 0x1C , 0xCA , 0x2B , 0xA7 , 0x8A , 0x09 , 0x81 , 0xE7 , 0x53 , 0xAA , 0xFF , 0x6F , 0x8E , 0x91 , 0xF1 , 0xF0 , 0xA4 , 0x46 , 0x3A , 0x7D , 0x54 , 0xEB , 0x2F , 0xC1 , 0xC0 , 0x0E , 0xBD , 0xE1 , 0x6C , 0x64 , 0xBE , 0xE4 , 0x02 , 0x3C , 0x5A , 0xA8 , 0x9F , 0x37 , 0xAF , 0xA0 , 0x13 , 0xED , 0x1B , 0xEC , 0x8B , 0x3E , 0x7E , 0x27 , 0x99 , 0x75 , 0xAB , 0xFE , 0xD9 , 0x3F , 0xF3 , 0xEA , 0x70 , 0xF7 , 0x95 , 0xBA , 0x1D , 0x40 , 0xB0 , 0xF9 , 0xE5 , 0xF8 , 0x06 , 0xBC , 0xB6 , 0x03 , 0xC9 , 0x10 , 0x9C , 0x2E , 0x89 , 0x5C , 0x7F , 0xB1 , 0x1A , 0xD6 , 0x90 , 0xAE , 0xDA , 0xE6 , 0x5E , 0xB9 , 0x84 , 0xE9 , 0x55 , 0xBB , 0xC7 , 0x0A , 0xE0 , 0x66 , 0xF2 , 0xD8 , 0xCB , 0x00 , 0x12 , 0xB8 , 0x17 , 0x94 , 0x6A , 0x4A , 0x01 , 0x24 , 0x14 , 0x51 , 0x07 , 0x65 , 0x21 , 0xC8 , 0x38 , 0xFD , 0x8F , 0xC4 , 0xF5 , 0xFC , } func getloss() (ret []byte) { m : = make( map [byte] bool ) for i : = 8 ; i < 256 ; i + + { m[t2tb[i]] = true } for i : = 0 ; i < 256 ; i + + { if !m[byte(i)] { ret = append(ret, byte(i)) } } return } / / 排列算法 func permutations(arr []byte) [][]byte { var helper func([]byte, int ) res : = [][]byte{} helper = func(arr []byte, n int ) { if n = = 1 { tmp : = make([]byte, len (arr)) copy(tmp, arr) res = append(res, tmp) } else { for i : = 0 ; i < n; i + + { helper(arr, n - 1 ) if n % 2 = = 1 { tmp : = arr[i] arr[i] = arr[n - 1 ] arr[n - 1 ] = tmp } else { tmp : = arr[ 0 ] arr[ 0 ] = arr[n - 1 ] arr[n - 1 ] = tmp } } } } helper(arr, len (arr)) return res } / / 第一个校验算法 func checksk(c [ 256 ]byte) bool { var sss [ 256 * 2 ]byte var kkk [ 256 ][ 256 ]byte maxn : = [] int { 2 , 4 , 8 , 0x10 , 0x20 , 0x40 , 0x80 } for i : = 0 ; i < 256 ; i + + { sss[ 0 ] = c[i] sss[ 1 ] = byte(i + 1 ) var ps int k : = maxn[ 0 ] for _, n : = range maxn { for j : = 0 ; j < n; j + + { sss[k] = c[sss[ps]] sss[k + 1 ] = sss[ps] + 1 k + = 2 ps + + } } for j : = 0 ; j < 256 ; j + + { kkk[i][sss[ps]] + + ps + + } } var r1, r2, r3, r4 int for i : = 0 ; i < 256 ; i + + { if kkk[i][ 0 ] ! = 0 { r1 + + } if kkk[i][ 40 - 26 ] ! = 0 { r2 + + } if kkk[i][ 40 ] ! = 0 { r3 + + } if kkk[i][ 40 + 39 ] ! = 0 { r4 + + } } return r1 = = 169 && r2 = = 172 && r3 = = 167 && r4 > 200 } / / 要反一下打印 func printHex(p []byte) { for _, v : = range p { c : = ((v & 0xf ) << 4 ) | ((v & 0xf0 ) >> 4 ) fmt.Printf( "%X" , c) } fmt.Println() } / / 求解第一部分 func t2p1() { / / 获取 tb 中缺失的 8 个数 loss : = getloss() / / 排列所有可能 8 ! = 40320 for _, pad : = range permutations(loss) { var t [ 256 ]byte copy(t[: 8 ], pad) copy(t[ 8 :], t2tb[ 8 :]) / / 求出满足第一个校验的 pad if checksk(t) { printHex(pad) } } } / / 输入 前半部分 结果后 / / 直接 dump 内存获取 tb变换 的结果 var t2tb2 = []byte{ 0xC1 , 0x9B , 0x7F , 0x58 , 0x64 , 0xD5 , 0x77 , 0x21 , 0x74 , 0xEB , 0x14 , 0xBF , 0xDF , 0x25 , 0x5A , 0x37 , 0x85 , 0x2C , 0xAF , 0x8C , 0xDA , 0x26 , 0xE2 , 0x7A , 0x87 , 0x4C , 0x60 , 0x99 , 0x54 , 0x3C , 0x95 , 0xC0 , 0xB9 , 0x0C , 0xBC , 0x0E , 0xE7 , 0x2D , 0x86 , 0xBE , 0x67 , 0xD3 , 0xD8 , 0xFC , 0x30 , 0xB6 , 0xC8 , 0x57 , 0x1E , 0x62 , 0x3E , 0xCE , 0xA0 , 0xCD , 0xF5 , 0xEE , 0xA7 , 0xCF , 0x45 , 0xFE , 0xD0 , 0x80 , 0x05 , 0xAD , 0x13 , 0xF3 , 0xB7 , 0x6B , 0x22 , 0x2B , 0xBD , 0x69 , 0x42 , 0x4B , 0xA5 , 0xEA , 0xA6 , 0xD2 , 0x6F , 0x4F , 0x4E , 0x07 , 0xE1 , 0x36 , 0x01 , 0xB5 , 0xAA , 0xB1 , 0x94 , 0x0B , 0x35 , 0x3A , 0xC7 , 0x49 , 0x53 , 0x82 , 0xC3 , 0x7B , 0x32 , 0xFF , 0x19 , 0xC4 , 0xF1 , 0xC9 , 0xE8 , 0xF7 , 0x56 , 0x15 , 0xA3 , 0x46 , 0x89 , 0x43 , 0x9D , 0x8F , 0x20 , 0xEF , 0xBB , 0x2A , 0xCB , 0x09 , 0x93 , 0x4A , 0x1C , 0xE3 , 0x33 , 0xD1 , 0xE0 , 0x1D , 0x72 , 0x7C , 0x27 , 0xE9 , 0x17 , 0x28 , 0x6D , 0x6A , 0xD9 , 0x00 , 0x9A , 0xE5 , 0x63 , 0xDE , 0x23 , 0x9F , 0x0D , 0x47 , 0x3B , 0x65 , 0x08 , 0x84 , 0x6C , 0x1A , 0x88 , 0x12 , 0xA1 , 0xA4 , 0xB3 , 0x18 , 0x24 , 0x1B , 0xD7 , 0x44 , 0xDB , 0xAC , 0x6E , 0x7D , 0x51 , 0x5E , 0xED , 0x50 , 0xD6 , 0x11 , 0x5B , 0x9C , 0xB4 , 0x68 , 0x3D , 0x2F , 0x03 , 0x40 , 0xBA , 0x2E , 0xCA , 0x02 , 0xE6 , 0xA8 , 0xEC , 0x83 , 0x06 , 0x5D , 0xB8 , 0x4D , 0x97 , 0x66 , 0xF0 , 0xFB , 0x8A , 0x55 , 0xAB , 0xB2 , 0x04 , 0xFA , 0x0A , 0x31 , 0x71 , 0xCC , 0x8B , 0x73 , 0xA9 , 0x48 , 0x5C , 0xF9 , 0x98 , 0xE4 , 0xC6 , 0x34 , 0xC5 , 0x7E , 0x81 , 0x75 , 0x90 , 0x1F , 0x92 , 0x3F , 0x9E , 0x10 , 0x29 , 0x52 , 0x39 , 0xF4 , 0x41 , 0x78 , 0x5F , 0x16 , 0x79 , 0xC2 , 0xB0 , 0xDD , 0xF2 , 0x61 , 0x0F , 0x70 , 0xD4 , 0x91 , 0xDC , 0xF6 , 0xF8 , 0xFD , 0x59 , 0x38 , 0x8D , 0x96 , 0xAE , 0x8E , 0x76 , 0xA2 , } / / 枚举 256 就能得出源 byte func dec( cmp byte, idx int ) byte { / / 第三部分算法 enc : = func(x byte) byte { c : = t2tb2[idx] for i : = 0 ; i < 8 ; i + + { if x& 1 ! = 0 { c = c + 1 } else { c = t2tb2[c] } x = x >> 1 } if idx = = 0 || idx = = 7 { c - - } return c } for i : = 0 ; i < 256 ; i + + { if enc(byte(i)) = = cmp { return byte(i) } } return 0 } / / 求解第二部分 func t2p2() { var arr []byte for i, c : = range []byte( "GoodJob~" ) { arr = append(arr, dec(c, i)) } printHex(arr) } func main() { t2p1() t2p2() } |
看雪招聘平台创建简历并且简历完整度达到90%及以上可获得500看雪币~
赞赏
他的文章