[原创]kctf2022 秋季赛 第十题 两袖清风 wp
2022-12-10 19:49:17 Author: bbs.pediy.com(查看原文) 阅读量:17 收藏

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

if len(flag) < 89:

    print('no!')

    return

n = 0x4F62187B5F6590C6CFF0FBDBBEBDAF60AA861BD2F66F8F7FFD57A66AE50DB7D2FFFFFFFFFFFFFFFFFFFFF

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)

那么作者在这里隐藏了离散对数问题吗?根据我们对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

decrypted = aes_decrypt_cbc(codes, encrypted, b'ABCDEF0123456789')

程序将解密后内容存入一个可读可写可执行的内存区域,最后使用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

// 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";

    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次穷举就能获得一个通过上述所有检查的输入。

经过分析,程序会根据输入的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

1

2

3

['1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF' + '9911' + '0F' + f'201{i}' * 7 + '01' for i in range(1, 10)]

1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F101110111011101110111011101101

1111110123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCEF99110F102110211021102110211021102102


文章来源: https://bbs.pediy.com/thread-275490.htm
如有侵权请联系:admin#unsafe.sh