-
-
[原创]kctf2022 秋季赛 第十题 两袖清风 wp
-
2022-12-10 19:44 14598
-
先看一看ida的f5
看见了1300行的f5,忍不住想关掉ida。
但是面对困难不要怕,经过一小会分析,我们恢复了一点细节。
作者在程序中插入了很多的 antidebug 技巧。同时字符串一般都用维吉尼亚进行了加密。
完成程序初始化之后,我们可以看到程序开始了校验逻辑。
将第一步份校验逻辑用python写下,可以发现那个模数n可以在factordb上查询到一个小因子p。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # flag = input('Please enter your key:') # print('Start cheking your key ...') if len (flag) < 89 : print ( 'no!' ) return n = 0x4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF # factored from factordb p = 193 q = n / / p assert isPrime(q) assert n = = p * q base = 0xB20446102D1C343D0575674CA28EBC0419BCFE4D75682C2AC81C9502454650BDDAEF6968AF269B54C182 _pow = int (flag[: 85 ], 16 ) powered = hex ( pow (base, _pow, n))[ 2 : ] if len (powered) % 2 = = 1 : powered = powered[: - 1 ] encrypted = bytes.fromhex(powered) |
乍一看像是 RSA ,实际上是一个离散对数问题,flag的第一部分是长度为85的十六进制数据。
$ base^{flagpartone} \mod n = C $
那么作者在这里隐藏了离散对数问题吗?根据我们对n的另一个因子q的分析,q-1不为一个光滑数,所以没有办法在多项式时间求解该离散对数问题,也就是说我们知道了C无法求得flagpartone。
继续往下分析。
作者将获得的 C 进行flag的第二部分,flag的85-88字节,必须为ABAB,ABBA的形式的,连接C作为魔改AES的密钥。密文为一段硬编码的 C2 。该AES使用CBC模式,iv是b'ABCDEF0123456789'。
1 2 3 4 | part2 = flag[ 85 : 89 ] codes = bytes.fromhex(vigenere(bytes.fromhex( '064C1E530006484807565B1B4A5003064A455D040A40440758071C1C57005D1C195754094F4F0652071B4A02000C484B54510E411853515C404806595A4F44005106404A0259594B4A02570E4A1C54545D4D4F53530F41445754061B485553081B1E5154084B4E50560C481B07520C4D1E5D040D4F1F55035D1C4457565E4A1E50560D1C1C54035B1A1C5353084F1956595E1C1F57545D1D4E5C020E4E4E0600084A1E00575E4E4E5D500A1C1E54555D401E00560D1A4D0150094E490652591C4D5207064D4A0055594E4B54050D1E1855530A49195C580A4F4A51570B4E1C00540C4A185607084B1C50070C40485452074D1950040E4F1C05565A1B4C5300061E4E52580A4B4D5D525D1C1857595E411F5C5109191F5C510F4C4C5256091A4B56540B481B005808401B00530E191C00570C194C5C570B194A07590C4B4B5C54594B4D575907491952550B484807515C4A1853075A1945560259484F000406494F52515C1B4A070406401E00075D4E1B00585A414D555859194950575C1B4F55075A494454535B4B1851510E4C4951005C4D1802535C1C1F56045D484C0259081C4B02550A4B4B5607061A4F57570F194A52530F4D45025207401E0557084A4D5C535A4B1B50530C4E4F52510F1E4E55520C4A1C5C590E4F1F07580F1A4D0154064B4957520E4B49525307494E06535A1A1807515A404554025C411801520B1D4D50575C1E1850580F484D54520A1C1C54030B4A485253094F1E5C53074D1F5556084C1C53075D1B455C040C481E0607091B185456091E44540559411B53585B481E5D58594F1E53575D414C0052071C4C53070C48195204061C45550408191956530A4A4C54510B1C4F55020B4D1C02075D4F1C54070C4A1957570A404F5D500B4B4A07595A411F06500D1E4457540D4A4E050559194507500E414C00540A1E1F54545B1B4F06035B4F4C06035E4A4D06520F4C1F05595D194A55055E4C4450550C4B4A07030849495C025E4E4402055D1A4907565E4A4B51555B4D4C005559481F50510C4C4806525C411954505B1E1E0657074E4B06040E1B1F50005C1C4D025708191E5605074B4A0556081A4F56000C4A4857585B4D1B00520B1E4E02565B4F4457590B4F4E02590A1C4B5C535B4C1B54540A481E54530D411C5002091B1851595949485558061D4956525B1E4D0654091E4A5C505C48485D59061D4D05530F1D1E5C070A4A4850045B411F57510D40485705081E1E56055A4E4D5C52591B1850575E4E1F05590C4E4551555A4A1B5500071C4E0558064F4550575C4F1B52590B484A5102094B4B53040D1C4D5D030E484501030E1B4E5D515A4B1B0555084E4855555D4B4D02520C4F1C56020B1B4406555A1C4F5303591E4400505E1A1F5453071C4452030E1A1F06075B1D4C02505D1B4C5255061D4B54530B4C4B5659074F4D540309411F02520E4A195C515D4B1901570B491B07510F404C55550B414A5300074C1E53000C1B4555590A494E57560E4A4B52555D1A4E55535C414453025E494E57570A1A1906530D4E4C00035B4A4D570359414A07000D484500515D4B1952585E1B1F55515A1A4901510B1E4B01535C404F5C025A401B07040C1A1B0558594C1952580F484A5C520C49455D00064D1851035A1B4C56000A1E4C02000F4E1950560C401E5400084D4A05565D1A4F53515B491C07070D4E1E01035E4B44565706414F5C075C1A455000074A4954590F48480759061E185D03061A4F06030D4C1E01070F491E5C005E484C5C57064A4E01055B4E1F560406194D5D025E4F4C55055C404D05050B481C50575A4C4954565A481B56580E484B5751064A4C0659061D4A52040A414E05020B4A4F0503594F4554070A1C195D0309191B05500C1C4B55040A4A1F57540E1A4551580B4D18505206194F55000C4E4F5C510F1C4550555D4D4557035D1B4555050C4F4406020A1B495207591C4857040A401B5C54094F1C51530E4A4C53550E4948025409494F015408494E005609191B54500C4F4C00590F1D4A54555C41190650084E48550308401C57560F414B50555A4A4901075C1B4D53030B4B1B07530C1E4806550A1D450555064E185400071E4A53045D1C4952540D404957545A1A4E5100091B1C05035E1A4F5204071B1F57565A4E185350594C4907520F1D4F51520A4A4F0552094E1B5151094C4D5004094E49020207401E54045B1D1E00045B4B1B01500848445605064B4F5D05084B4905515A491B0704591B485705064C1E5D590E1C1952525C1C1B06500B1C440756061B1F05075B194B54500B1A1F5400071D490500064D1951035C4B4C54590B1E4A01005C414B055406411907055B4D480500081E4F565607404A0058074C4F53530B4F1F05565D414F5203074F48075307484B5100084C4955030C1E485D520E4A4F5253064E1E05005A4F4C53590E1A1851005A1C1F52050E484406505E1C1B07020E1A4507545E484551050E1B1B06025B4A445359061D4A05520A1A4E50580A4D4E515708194F005907494952070A1B195704594B1E5354094D4902545E4B4D05045E1D4B00570D4C4802575D4E4D005209194853040B194E50020C1B4A00025D494951560D404502070D1D1E02520B1B49055707414E5D515A404B07500E1B445258081D1F05055D1A1E07540B1D18565608194901050E411B56540B4B1F07555A4C4F55030D404C54510C1D4953000F1C4807520C491E53565E4A1851535E4A1F5C055C4D4552585B4C4C57000819495003591E4D5C050A1A1850000A494801530A1A4B06035E4A4D505906404D53030B1A4E00570C411F0754064A4A575207481853575A4E1F53050E191C570507494952500D41445C00594C4A54500D4C1802040F41495202081B4453070A4E4D06555E4A4E00570A4F4457005E1D1955580F4D4C55045A1A4806550E4B445D505C1B4802560F4A4850520B1A4B52570B4E4B51565A404455030D4A19575706491B515507481C0504074C4A02545B401E50530F1B4456520B411901070C1E1F5D50071D4B5259591B1802540C4F1C52585A19445151064A4E05535A481F06055C1A4C545807481B57055C411F06505B4D180253091E1C06560F1B1F5356591C4C05030F4D490205084B4A01500E194E5D54594F4507590A191C05030C404950550F4B4405590F1A4C5D000F1E4C00040C41485C075A484D0551091C4D06030C1E1F01045C1E4D53595D40185C040B4F1B54030F1E4850555D4F4C5656074F185D0407491957515A1D4806525E194505560F4F485C525E4A180750591D1905535C4B4E51025D1C4F5D07094A4B06580F481C0255064E1C00005B1C4956530F481B05540C40195D545940480703084E1F05540F481C00570C4E4F5400064D4454020F491E01550C4B4D0053094D4802075E1D4C5C02064B455C515C1E4C06570E4D1B53555A4F1857045E1D1E01550E40455C040B4D1851070F1C1C51555B1A1F5D000E1D4D01580E4D4D53050E1E485D050B1A1F54570F4B445D56591A1C5751064D495C570A4A4B54570F4C4C54530F491806550B4E1854030E4E1C5C020B4E4B5D000D4B1E54570D1B4452070B404806555C401E55055E1D4507530B1A1F0251084D4D5C585E4948005809494A54565E1A4E5D59074A195652594F4A07050E4D4B0552064B1E5356081B4C02555949195C57594B1807580D1C4A06025B1B4800530F4D445605074A4D5C07094F4856520B4B4F01565E414C51520A484D5C5108401C02585A4E1E0155591B1B55560B4019060206484950075D401C06040C1D4B0557591D1E00030A4B4557545B4E4956590A404850500E4A4C5D030C484507535C4E4451575E1E1F0500591D4E54505B4C4A0200064B4E0557074A195C550E1A1907505E1D1B52570E4C1856570A4F4E56520B4D4C54020C4B4805530A4C4B52025A1C4D5C545E411F53535A4D4A5D510B414C5756071C4501515E1A1C5D5306191F5755094F4A01025D4A1E57050A4E1F535609401B53030D1E1B51020B1C1851520D1E4F5358084F1957045B4E1E5C0208401C57565D4F485003594E1C515706191C0500084D4B0105081C195D035B1E4952035E1E1E00000B4B4456545A4F4A5104591E4801025C1A1E53070F404A0500091D4C01040A4F4E50535D494C53005C4E1B05525E481E02570E484D53575C1A485254081C485058061A1E0102074C1E025259484955040C1B4852550D404A01025D4B4E02500C1B1B54595E4F4854510D1C1E50030A4C48025206491F565008194F05055C4A4F06550A4D4A505506414C02035D414A00565A1E1C0607084C4C0505094F455003084C4457020C4E440200074D1C55040B4A4A5D535D4E4452540A4B1807070E491807500A481950510C404C50565C1B4901045C191852005C4B4A5105591A4E5C530C194F5D02094A4F565707484D075107191C53035B1C1C56565D1E4C52555E1C4B57525A1E4B55555C1B1B060008484A53535D4B4555055A411C5D59091A4E5559061D1957520B1B1E05560C4D1954550649455D520C4D485305081D4B53540E4F1850595E4B4900075E191B0707591C1852500B194B5C525C1D18010206401F5D540D4A1E5653094F1906055D4F4B00025A1A1E07045D4B4407035E4F445C570B1B4955040C491F5303591A4557055D4A1900040E4F1C5C595C1B180556591E195759074F4856045C4D4902510A4B4C54510F194E5D070E4A1C05585B4D1C50580E4D4C51550B1B1B5055594F4D06075E4B4E0752084F190507591D1F57555A411C05580E414C53520F4F4F07045A4E485C520F4F1E5C560F4F4B0607094E1854580C494401075C194F5D005B4C4E00595D4E4D07045A4C1C5C560A1B4D01580E491B5C580C494557035A1D440754594F4A5452084A440704071B4B5D03064A1950570F404556540A4F480158084C1F51525D4A4F5200' ), "?x}da" ).decode()) encrypted = part2.encode() + encrypted # vigenere(encrypted, "Y?j0?") decrypted = aes_decrypt_cbc(codes, encrypted, b 'ABCDEF0123456789' ) |
之后解密的内容我们记为 Code1 。也就是“decrypted”。
程序将解密后内容存入一个可读可写可执行的内存区域,最后使用ZwQueueApcThread创建一个
异步程序调用,这里把它当成call就行了。值得注意的是,解密后的内容在拷贝的过程会出现\0截断问题。
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 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 | #include <stdlib.h> #include <stdio.h> #include <string.h> #include <assert.h> / / AES typedef struct { unsigned char rk[ 15 * 4 * 4 ]; / / round key unsigned char iv[ 16 ]; } AES_CONTEXT; const unsigned char Sbox[ 256 ] = { / / 0 1 2 3 4 5 6 7 8 9 a b c d e f 0x63 , 0x7c , 0x77 , 0x7b , 0xf2 , 0x6b , 0x6f , 0xc5 , 0x30 , 0x01 , 0x67 , 0x2b , 0xfe , 0xd7 , 0xab , 0x76 , / / 0 0xca , 0x82 , 0xc9 , 0x7d , 0xfa , 0x59 , 0x47 , 0xf0 , 0xad , 0xd4 , 0xa2 , 0xaf , 0x9c , 0xa4 , 0x72 , 0xc0 , / / 1 0xb7 , 0xfd , 0x93 , 0x26 , 0x36 , 0x3f , 0xf7 , 0xcc , 0x34 , 0xa5 , 0xe5 , 0xf1 , 0x71 , 0xd8 , 0x31 , 0x15 , / / 2 0x04 , 0xc7 , 0x23 , 0xc3 , 0x18 , 0x96 , 0x05 , 0x9a , 0x07 , 0x12 , 0x80 , 0xe2 , 0xeb , 0x27 , 0xb2 , 0x75 , / / 3 0x09 , 0x83 , 0x2c , 0x1a , 0x1b , 0x6e , 0x5a , 0xa0 , 0x52 , 0x3b , 0xd6 , 0xb3 , 0x29 , 0xe3 , 0x2f , 0x84 , / / 4 0x53 , 0xd1 , 0x00 , 0xed , 0x20 , 0xfc , 0xb1 , 0x5b , 0x6a , 0xcb , 0xbe , 0x39 , 0x4a , 0x4c , 0x58 , 0xcf , / / 5 0xd0 , 0xef , 0xaa , 0xfb , 0x43 , 0x4d , 0x33 , 0x85 , 0x45 , 0xf9 , 0x02 , 0x7f , 0x50 , 0x3c , 0x9f , 0xa8 , / / 6 0x51 , 0xa3 , 0x40 , 0x8f , 0x92 , 0x9d , 0x38 , 0xf5 , 0xbc , 0xb6 , 0xda , 0x21 , 0x10 , 0xff , 0xf3 , 0xd2 , / / 7 0xcd , 0x0c , 0x13 , 0xec , 0x5f , 0x97 , 0x44 , 0x17 , 0xc4 , 0xa7 , 0x7e , 0x3d , 0x64 , 0x5d , 0x19 , 0x73 , / / 8 0x60 , 0x81 , 0x4f , 0xdc , 0x22 , 0x2a , 0x90 , 0x88 , 0x46 , 0xee , 0xb8 , 0x14 , 0xde , 0x5e , 0x0b , 0xdb , / / 9 0xe0 , 0x32 , 0x3a , 0x0a , 0x49 , 0x06 , 0x24 , 0x5c , 0xc2 , 0xd3 , 0xac , 0x62 , 0x91 , 0x95 , 0xe4 , 0x79 , / / a 0xe7 , 0xc8 , 0x37 , 0x6d , 0x8d , 0xd5 , 0x4e , 0xa9 , 0x6c , 0x56 , 0xf4 , 0xea , 0x65 , 0x7a , 0xae , 0x08 , / / b 0xba , 0x78 , 0x25 , 0x2e , 0x1c , 0xa6 , 0xb4 , 0xc6 , 0xe8 , 0xdd , 0x74 , 0x1f , 0x4b , 0xbd , 0x8b , 0x8a , / / c 0x70 , 0x3e , 0xb5 , 0x66 , 0x48 , 0x03 , 0xf6 , 0x0e , 0x61 , 0x35 , 0x57 , 0xb9 , 0x86 , 0xc1 , 0x1d , 0x9e , / / d 0xe1 , 0xf8 , 0x98 , 0x11 , 0x69 , 0xd9 , 0x8e , 0x94 , 0x9b , 0x1e , 0x87 , 0xe9 , 0xce , 0x55 , 0x28 , 0xdf , / / e 0x8c , 0xa1 , 0x89 , 0x0d , 0xbf , 0xe6 , 0x42 , 0x68 , 0x41 , 0x99 , 0x2d , 0x0f , 0xb0 , 0x54 , 0xbb , 0x16 / / f }; const unsigned char InvSbox[ 256 ] = { / / 0 1 2 3 4 5 6 7 8 9 a b c d e f 0x52 , 0x09 , 0x6a , 0xd5 , 0x30 , 0x36 , 0xa5 , 0x38 , 0xbf , 0x40 , 0xa3 , 0x9e , 0x81 , 0xf3 , 0xd7 , 0xfb , / / 0 0x7c , 0xe3 , 0x39 , 0x82 , 0x9b , 0x2f , 0xff , 0x87 , 0x34 , 0x8e , 0x43 , 0x44 , 0xc4 , 0xde , 0xe9 , 0xcb , / / 1 0x54 , 0x7b , 0x94 , 0x32 , 0xa6 , 0xc2 , 0x23 , 0x3d , 0xee , 0x4c , 0x95 , 0x0b , 0x42 , 0xfa , 0xc3 , 0x4e , / / 2 0x08 , 0x2e , 0xa1 , 0x66 , 0x28 , 0xd9 , 0x24 , 0xb2 , 0x76 , 0x5b , 0xa2 , 0x49 , 0x6d , 0x8b , 0xd1 , 0x25 , / / 3 0x72 , 0xf8 , 0xf6 , 0x64 , 0x86 , 0x68 , 0x98 , 0x16 , 0xd4 , 0xa4 , 0x5c , 0xcc , 0x5d , 0x65 , 0xb6 , 0x92 , / / 4 0x6c , 0x70 , 0x48 , 0x50 , 0xfd , 0xed , 0xb9 , 0xda , 0x5e , 0x15 , 0x46 , 0x57 , 0xa7 , 0x8d , 0x9d , 0x84 , / / 5 0x90 , 0xd8 , 0xab , 0x00 , 0x8c , 0xbc , 0xd3 , 0x0a , 0xf7 , 0xe4 , 0x58 , 0x05 , 0xb8 , 0xb3 , 0x45 , 0x06 , / / 6 0xd0 , 0x2c , 0x1e , 0x8f , 0xca , 0x3f , 0x0f , 0x02 , 0xc1 , 0xaf , 0xbd , 0x03 , 0x01 , 0x13 , 0x8a , 0x6b , / / 7 0x3a , 0x91 , 0x11 , 0x41 , 0x4f , 0x67 , 0xdc , 0xea , 0x97 , 0xf2 , 0xcf , 0xce , 0xf0 , 0xb4 , 0xe6 , 0x73 , / / 8 0x96 , 0xac , 0x74 , 0x22 , 0xe7 , 0xad , 0x35 , 0x85 , 0xe2 , 0xf9 , 0x37 , 0xe8 , 0x1c , 0x75 , 0xdf , 0x6e , / / 9 0x47 , 0xf1 , 0x1a , 0x71 , 0x1d , 0x29 , 0xc5 , 0x89 , 0x6f , 0xb7 , 0x62 , 0x0e , 0xaa , 0x18 , 0xbe , 0x1b , / / a 0xfc , 0x56 , 0x3e , 0x4b , 0xc6 , 0xd2 , 0x79 , 0x20 , 0x9a , 0xdb , 0xc0 , 0xfe , 0x78 , 0xcd , 0x5a , 0xf4 , / / b 0x1f , 0xdd , 0xa8 , 0x33 , 0x88 , 0x07 , 0xc7 , 0x31 , 0xb1 , 0x12 , 0x10 , 0x59 , 0x27 , 0x80 , 0xec , 0x5f , / / c 0x60 , 0x51 , 0x7f , 0xa9 , 0x19 , 0xb5 , 0x4a , 0x0d , 0x2d , 0xe5 , 0x7a , 0x9f , 0x93 , 0xc9 , 0x9c , 0xef , / / d 0xa0 , 0xe0 , 0x3b , 0x4d , 0xae , 0x2a , 0xf5 , 0xb0 , 0xc8 , 0xeb , 0xbb , 0x3c , 0x83 , 0x53 , 0x99 , 0x61 , / / e 0x17 , 0x2b , 0x04 , 0x7e , 0xba , 0x77 , 0xd6 , 0x26 , 0xe1 , 0x69 , 0x14 , 0x63 , 0x55 , 0x21 , 0x0c , 0x7d / / f }; void KeyExpansion(AES_CONTEXT * ctx, const unsigned char * key) { unsigned char t[ 4 ]; unsigned char tmp; memcpy(ctx - >rk, key, 32 ); for ( int i = 8 ; i < 15 * 4 ; i + + ) { memcpy(t, ctx - >rk + 4 * (i - 1 ), 4 ); if (i % 8 ) { if (i % 8 = = 4 ) { t[ 0 ] = Sbox[t[ 0 ]]; t[ 1 ] = Sbox[t[ 1 ]]; t[ 2 ] = Sbox[t[ 2 ]]; t[ 3 ] = Sbox[t[ 3 ]]; } } else { tmp = Sbox[t[ 1 ]]; t[ 1 ] = Sbox[t[ 2 ]]; t[ 2 ] = Sbox[t[ 3 ]]; t[ 3 ] = Sbox[t[ 0 ]]; unsigned char rc = 1 ; for ( int j = 0 ; j < i / 8 - 1 ; j + + ) rc = ( 0x1B * (rc >> 7 )) ^ ( 2 * rc); t[ 0 ] = rc ^ tmp; } ctx - >rk[i * 4 ] = ctx - >rk[i * 4 - 32 ] ^ t[ 0 ]; ctx - >rk[i * 4 + 1 ] = ctx - >rk[i * 4 - 31 ] ^ t[ 1 ]; ctx - >rk[i * 4 + 2 ] = ctx - >rk[i * 4 - 30 ] ^ t[ 2 ]; ctx - >rk[i * 4 + 3 ] = ctx - >rk[i * 4 - 29 ] ^ t[ 3 ]; } } unsigned char FFmul(unsigned char a, unsigned char b) { unsigned char bw[ 4 ]; unsigned char res = 0 ; int i; bw[ 0 ] = b; for (i = 1 ; i < 4 ; i + + ) { bw[i] = bw[i - 1 ] << 1 ; if (bw[i - 1 ] & 0x80 ) { bw[i] ^ = 0x1b ; } } for (i = 0 ; i < 4 ; i + + ) { if ((a >> i) & 0x01 ) { res ^ = bw[i]; } } return res; } void SubBytes(AES_CONTEXT * ctx, unsigned char * state) { for ( int i = 0 ; i < 16 ; i + + ) state[i] = Sbox[state[i]]; } void ShiftRows(AES_CONTEXT * ctx, unsigned char * state) { unsigned char tmp[ 4 ]; * (unsigned int * ) tmp = * (unsigned int * ) (state + 4 ); state[ 7 ] = tmp[ 0 ]; state[ 4 ] = tmp[ 1 ]; state[ 5 ] = tmp[ 2 ]; state[ 6 ] = tmp[ 3 ]; * (unsigned int * ) tmp = * (unsigned int * ) (state + 8 ); state[ 10 ] = tmp[ 0 ]; state[ 11 ] = tmp[ 1 ]; state[ 8 ] = tmp[ 2 ]; state[ 9 ] = tmp[ 3 ]; * (unsigned int * ) tmp = * (unsigned int * ) (state + 12 ); state[ 13 ] = tmp[ 0 ]; state[ 14 ] = tmp[ 1 ]; state[ 15 ] = tmp[ 2 ]; state[ 12 ] = tmp[ 3 ]; } void MixColumns(AES_CONTEXT * ctx, unsigned char * state) { unsigned char tmp[ 16 ]; memset(tmp, 0. , 16 ); for ( int i = 0 ; i < 4 ; i + + ) { tmp[i] = FFmul( 2 , state[ 0 + i]) ^ FFmul( 3 , state[ 4 + i]) ^ FFmul( 1 , state[ 8 + i]) ^ FFmul( 1 , state[ 12 + i]); tmp[i + 4 ] = FFmul( 1 , state[ 0 + i]) ^ FFmul( 2 , state[ 4 + i]) ^ FFmul( 3 , state[ 8 + i]) ^ FFmul( 1 , state[ 12 + i]); tmp[i + 8 ] = FFmul( 1 , state[ 0 + i]) ^ FFmul( 1 , state[ 4 + i]) ^ FFmul( 2 , state[ 8 + i]) ^ FFmul( 3 , state[ 12 + i]); tmp[i + 12 ] = FFmul( 3 , state[ 0 + i]) ^ FFmul( 1 , state[ 4 + i]) ^ FFmul( 1 , state[ 8 + i]) ^ FFmul( 2 , state[ 12 + i]); } memcpy(state, tmp, 16 ); } void AddRoundKey(AES_CONTEXT * ctx, unsigned char * state, unsigned char * k) { for ( int i = 0 ; i < 4 ; i + + ) { for ( int j = 0 ; j < 4 ; j + + ) { state[i * 4 + j] ^ = k[j * 4 + i]; } } } void InvSubBytes(AES_CONTEXT * ctx, unsigned char * state) { for ( int i = 0 ; i < 16 ; i + + ) state[i] = InvSbox[state[i]]; } void InvShiftRows(AES_CONTEXT * ctx, unsigned char * state) { unsigned char tmp[ 4 ]; tmp[ 0 ] = state[ 7 ]; tmp[ 1 ] = state[ 4 ]; tmp[ 2 ] = state[ 5 ]; tmp[ 3 ] = state[ 6 ]; * (unsigned int * ) (state + 4 ) = * (unsigned int * ) tmp; tmp[ 0 ] = state[ 10 ]; tmp[ 1 ] = state[ 11 ]; tmp[ 2 ] = state[ 8 ]; tmp[ 3 ] = state[ 9 ]; * (unsigned int * ) (state + 8 ) = * (unsigned int * ) tmp; tmp[ 0 ] = state[ 13 ]; tmp[ 1 ] = state[ 14 ]; tmp[ 2 ] = state[ 15 ]; tmp[ 3 ] = state[ 12 ]; * (unsigned int * ) (state + 12 ) = * (unsigned int * ) tmp; } void InvMixColumns(AES_CONTEXT * ctx, unsigned char * state) { unsigned char tmp[ 16 ]; memset(tmp, 0. , 16 ); for ( int i = 0 ; i < 4 ; i + + ) { tmp[i] = FFmul( 0x0e , state[ 0 + i]) ^ FFmul( 0x0b , state[ 4 + i]) ^ FFmul( 0x0d , state[ 8 + i]) ^ FFmul( 0x09 , state[ 12 + i]); tmp[i + 4 ] = FFmul( 0x09 , state[ 0 + i]) ^ FFmul( 0x0e , state[ 4 + i]) ^ FFmul( 0x0b , state[ 8 + i]) ^ FFmul( 0x0d , state[ 12 + i]); tmp[i + 8 ] = FFmul( 0x0d , state[ 0 + i]) ^ FFmul( 0x09 , state[ 4 + i]) ^ FFmul( 0x0e , state[ 8 + i]) ^ FFmul( 0x0b , state[ 12 + i]); tmp[i + 12 ] = FFmul( 0x0b , state[ 0 + i]) ^ FFmul( 0x0d , state[ 4 + i]) ^ FFmul( 0x09 , state[ 8 + i]) ^ FFmul( 0x0e , state[ 12 + i]); } memcpy(state, tmp, 16 ); } void aes_init(AES_CONTEXT * ctx, const unsigned char * key, const void * iv) { / / memcpy(ctx - >Sbox, sBox, 256 ); / / memcpy(ctx - >InvSbox, invsBox, 256 ); KeyExpansion(ctx, key); if (iv) memcpy(ctx - >iv, iv, 16 ); } unsigned char * aes_decrypt_block(AES_CONTEXT * ctx, unsigned char * input ) { unsigned char state[ 16 ]; int i, r, c; for ( int i = 0 ; i < 4 ; i + + ) { for ( int j = 0 ; j < 4 ; j + + ) { state[i * 4 + j] = input [j * 4 + i]; } } AddRoundKey(ctx, state, ctx - >rk + 14 * 16 ); for ( int i = 13 ; i > 0 ; i - - ) { InvSubBytes(ctx, state); InvShiftRows(ctx, state); AddRoundKey(ctx, state, ctx - >rk + 16 * i); InvMixColumns(ctx, state); } InvSubBytes(ctx, state); InvShiftRows(ctx, state); AddRoundKey(ctx, state, ctx - >rk); for ( int i = 0 ; i < 4 ; i + + ) { for ( int j = 0 ; j < 4 ; j + + ) { input [i * 4 + j] = state[j * 4 + i]; } } return input ; } void aes_decrypt_ecb(const void * key, void * data, int data_len) { assert (data_len % 16 = = 0 ); AES_CONTEXT ctx; aes_init(&ctx, (const unsigned char * ) key, NULL); unsigned char * _data = (unsigned char * ) data; for ( int i = 0 ; i < data_len / 16 ; i + + ) { aes_decrypt_block(&ctx, _data); _data + = 16 ; } } void aes_decrypt_cbc(const void * key, const void * iv, void * data, int data_len) { assert (data_len % 16 = = 0 ); AES_CONTEXT ctx; aes_init(&ctx, (const unsigned char * ) key, iv); unsigned char * _data = (unsigned char * ) data; unsigned char buf[ 16 ]; for ( int i = 0 ; i < data_len / 16 ; i + + ) { memcpy(buf, _data, 16 ); aes_decrypt_block(&ctx, _data); for ( int j = 0 ; j < 16 ; j + + ) _data[j] ^ = ctx.iv[j]; _data + = 16 ; memcpy(ctx.iv, buf, 16 ); } } int main() { unsigned char data[] = "\x94\xC7\xA9\x05\xC7\xDC\x74\xB9\x28\x9E\x58\x9C\x98\xDA\x3A\xBD" "\xD3\x56\x72\xB3\x8C\x7F\xA3\x06\x00\x19\xE7\x0C\x85\xB8\xE7\x9D" "\x09\x87\xF8\xF3\x7F\x61\x2A\x05\xB5\x27\x20\x99\x35\x9C\x51\x27" "\xCC\x55\x73\x34\x73\x0F\xC3\x35\xC9\xE2\x7B\x1B\xBD\x93\x7A\x2C" "\x47\x2D\xA0\xBD\xBA\x72\x77\xD2\x8A\xDB\x35\xBE\x38\xC1\x63\xBA" "\x72\xCD\x6A\x63\x91\x5D\xC0\x4B\x8C\xD7\x2B\x0E\x16\x64\xB3\xFD" ; unsigned char key[] = "\x44\x44\x45\x45\xaf\x20\x5d\xb8\xe5\x0e\xb8\x95\x2b\x78\x22\xcc\x7a\x3a\xeb\x55\x0c\x0a\xc9\xb7\xfc\xf1\x59\xc0\xe8\xc7\x29\xf4" ; unsigned char iv[] = "ABCDEF0123456789" ; #define BLOCK_SIZE 4 unsigned char tmp[ 16 * BLOCK_SIZE]; for ( int i = 0 ; i < 100 ; i + + ) { memcpy(tmp, data, 16 * BLOCK_SIZE); key[ 0 ] = 0x30 + i / 10 ; key[ 1 ] = 0x30 + i / 10 ; key[ 2 ] = 0x30 + i % 10 ; key[ 3 ] = 0x30 + i % 10 ; aes_decrypt_cbc(key, iv, tmp, 16 * BLOCK_SIZE); if (tmp[ 0 ] = = 0xC3 ) break ; } printf( "%s\n" , tmp[ 0 ] = = 0xc3 ? "Yes." : "No." ); for ( int i = 0 ; i < 2 ; i + + ) { for ( int j = 0 ; j < 16 ; j + + ) { printf( "%02x " , key[i * 16 + j]); } putchar( '\n' ); } putchar( '\n' ); for ( int i = 0 ; i < BLOCK_SIZE; i + + ) { for ( int j = 0 ; j < 16 ; j + + ) { printf( "%02x " , tmp[i * 16 + j]); } putchar( '\n' ); } return 0 ; } |
仅仅魔改了密钥扩展,该AES为修改密钥扩展的14轮AES。与常见的AES-128不同,这个AES使用256bit(32字节)密钥,加密块却是128bit。在98k成员的有限的知识中应该不存在算法缺点。
如果我们假设这里能顺利运行,我们的问题就变成了需要猜测明文可执行指令,和密文,求出密钥。显然这个场景的是不可解问题。约等于AES的已知明文攻击。在没有实现缺陷的情况下,不可求出密钥。
所以,我们认为,以上两步中我们可以控制输入的flag的第一和第二部分控制AES解密结果,只要确保第一个字节为 0xc3 也就是 ret 指令就能让程序完美运行。平均256次穷举就能获得一个通过上述所有检查的输入。
该步骤最多可产生 16 ^ 85 / 256 种解。
然后程序使用UUID的方式编码shellcode。
经过分析,程序会根据输入的flag条件,在程序main函数中存在正确或者失败的字符串的内存中写入good或者bad。所以我们可以根据第三部分来控制main函数中的输出,我们想覆盖main函数中字符串的位置为220。根据分析我们需要控制 ‘kctf’ + 数据长度单字节 + 数据 为20字节。
并且满足以下约束条件。
1 2 3 4 5 6 7 8 9 10 11 12 13 | flag: a - z: 1 0 - 9 ,A - Z: 0 other: 2 maybe, 3 debug: xx type [A[i] * 10 + B[i]] ! = 1 A[i + 1 ] - A[i] = = 1 || A[i + 1 ] - A[i] = = - 1 || B[i + 1 ] - B[i] = = 1 || B[i + 1 ] - B[i] = = - 1 B[ 14 ] = = 0 || B[ 14 ] = = 9 || A[ 14 ] = = 0 || A[ 14 ] = = 9 B[ 14 ] ! = B[ 0 ] || A[ 14 ] ! = A[ 0 ] B[ 0 ] = = 0 type [A[i] * 10 + B[i] + 100 ] ! = 1 B[ 14 ] < = 9 |
A数组代表输入hex中的的高位组成的数组,B数组代表输入hex中的的低位组成的数组。
这里宽松的约束条件也能产生很多组解。
笔者这里给出九组解。
1 2 3 | [ '1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF' + '9911' + '0F' + f '201{i}' * 7 + '01' for i in range ( 1 , 10 )] 1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F101110111011101110111011101101 1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F102110211021102110211021102102 |
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法