# Grey Cat The Flag 2023 Qualifiers # WEB Long https://github.com/longkd719/CTFWriteUps/tree/main/2023/Grey%20CTF%202023%20Quals # CRYPTO Quốc https://hackmd.io/@GP1HnYyzQ3CATjnYWZeo4Q/BJ-H-sirn # PWN Quang https://github.com/wan-hyhty/CTFs_competition/tree/main/grey_cat_2023#readme # REV ## Crackme1 Đầu tiên deofuscation lại code: ``` window['addEventListener']('load', () => { document['getElementById']('submitButton')['addEventListener']('click', buttonClick); }); function buttonClick() { var key = document['getElementById']('textKey')['value']; // We replicate the key up to a length of 0x400 while (key['length'] < 0x400) key = key + key; key = key['substring'](0x0, 0x400); display_image(key); var cipher = [0xc3, 0xb8, 0xb3, 0x42, 0xb6, 0xc2, 0x1c, 0xa4, 0xce, 0x45, 0x6, 0x3b, 0x1f, 0x1c, 0x66, 0xb1, 0x6c, 0x9a, 0x36, 0xe5, 0x14, 0xbf, 0x18, 0x6e], key_sched = rc4(key, 0x18), flag = ''; for (var i = 0x0; i < 0x18; ++i) { flag += String['fromCharCode'](cipher[i] ^ key_sched[i]); } if (flag['startsWith']('grey{')) document['querySelector']('#flag')['textContent'] = flag; } function rc4(key, len) { var a = [], j = 0x0, tmp, permutation = []; for (var i = 0x0; i < 0x100; i++) { a[i] = i; } for (i = 0x0; i < 0x100; i++) { j = (j + a[i] + key['charCodeAt'](i % key['length'])) % 0x100; tmp = a[i]; a[i] = a[j]; a[j] = tmp; } i = 0x0, j = 0x0; for (var k = 0x0; k < len; k++) { i = (i + 0x1) % 0x100; j = (j + a[i]) % 0x100; tmp = a[i]; a[i] = a[j]; a[j] = tmp; permutation['push'](a[(a[i] + a[j]) % 0x100]); } return permutation; } ``` Thực hiện check key trong hàm `display_image(key)` Hàm display_image() ``` function display_image(input) { var a = [0x0, 0x0, 0x0, 0x0], b = [0x0, 0x0, 0x0, 0x0], c = [0x0, 0x0, 0x0, 0x0], d = [0x0, 0x0, 0x0, 0x0], e = [0x41, 0x41, 0x41, 0x41]; for (var i = 0x0; i < 0x104; ++i) { const _0x3d0205 = init_buffer_vertex(context_canvas, new Float32Array(a), a_shader), _0x1bbc48 = init_buffer_vertex(context_canvas, new Float32Array(b), b_shader), _0x12ff68 = init_buffer_vertex(context_canvas, new Float32Array(c), c_shader), _0x358438 = init_buffer_vertex(context_canvas, new Float32Array(d), d_shader), _0x31fd87 = init_buffer_vertex(context_canvas, new Float32Array(e), e_shader), _0x5efde3 = context_canvas['createTransformFeedback'](); context_canvas['bindTransformFeedback'](context_canvas['TRANSFORM_FEEDBACK'], _0x5efde3); const feedback_shader = init_buffer(context_canvas, a['length'] * 0x4); context_canvas['bindBufferBase'](context_canvas['TRANSFORM_FEEDBACK_BUFFER'], 0x0, feedback_shader); context_canvas['bindTransformFeedback'](context_canvas['TRANSFORM_FEEDBACK'], null); context_canvas['bindBuffer'](context_canvas['ARRAY_BUFFER'], null); context_canvas['useProgram'](program12); context_canvas['bindVertexArray'](_0x37ea82); context_canvas['bindTransformFeedback'](context_canvas['TRANSFORM_FEEDBACK'], _0x5efde3); context_canvas['beginTransformFeedback'](context_canvas['POINTS']); context_canvas['drawArrays'](context_canvas['POINTS'], 0x0, a['length']); context_canvas['endTransformFeedback'](); context_canvas['bindTransformFeedback'](context_canvas['TRANSFORM_FEEDBACK'], null); // We get the feedback from the WebGL shader const f = new Float32Array(a['length']); context_canvas['bindBuffer'](context_canvas['ARRAY_BUFFER'], feedback_shader); context_canvas['getBufferSubData'](context_canvas['ARRAY_BUFFER'], 0x0, f); for (var j = 0x0; j < 0x4; ++j) { d[j] = Math['round'](f[j]) % 0x100; e = e['fill'](input['charCodeAt'](d[j])); a[j] = matrix1[d[0x0]][j]; b[j] = matrix2[d[0x0]][j]; c[j] = matrix3[d[0x0]][j]; } context_canvas['uniform4fv'](s_shader, d); context_query_c['clearColor'](0x0, 0x0, 0x0, 0x0), context_query_c['clear'](context_canvas['COLOR_BUFFER_BIT']); context_query_c['useProgram'](program34); context_query_c['activeTexture'](context_query_c['TEXTURE0'] + 0x1); context_query_c['bindTexture'](context_query_c['TEXTURE_2D'], _0x3d5c0d); context_query_c['texParameteri'](context_query_c['TEXTURE_2D'], context_query_c['TEXTURE_WRAP_S'], context_query_c['CLAMP_TO_EDGE']); context_query_c['texParameteri'](context_query_c['TEXTURE_2D'], context_query_c['TEXTURE_WRAP_T'], context_query_c['CLAMP_TO_EDGE']); context_query_c['texParameteri'](context_query_c['TEXTURE_2D'], context_query_c['TEXTURE_MIN_FILTER'], context_query_c['NEAREST']); context_query_c['texParameteri'](context_query_c['TEXTURE_2D'], context_query_c['TEXTURE_MAG_FILTER'], context_query_c['NEAREST']); // We need to have d[0x1] = 1 to display the good image! context_query_c['activeTexture'](context_query_c['TEXTURE0']), context_query_c['bindTexture'](context_query_c['TEXTURE_2D'], array_images[d[0x1]]); context_query_c['bindVertexArray'](_0x5745db), context_query_c['drawArrays'](context_query_c['TRIANGLES'], 0x0, 0x6); } } ``` Script tìm key: ``` import sys matrix1 = [[0x1, 0x0, 0x1, 0x1], ...] matrix2 = [[0xe5, 0x0, 0x0, 0x0], ...] matrix3 = [[0x0, 0x0, 0x0, 0x0], ...] def compute(a,b,c,d,e): res = a * d + b + c * e #print(res) if res >= 0: return res % 256 else: return - ((-res) % 256) if __name__ == '__main__': key = bytearray([0 for i in range(20)]) a = [0x0, 0x0, 0x0, 0x0] b = [0x0, 0x0, 0x0, 0x0] c = [0x0, 0x0, 0x0, 0x0] d = [0x0, 0x0, 0x0, 0x0] e = [0x41, 0x41, 0x41, 0x41] for i in range(0x104): if b[2] != 0: key[d[3]] = -b[2] e = [key[d[3]] for j in range(4)] if d[2]: d = [0 for j in range(4)] else: d = [compute(a[j],b[j],c[j],d[j],e[j]) for j in range(4)] a = matrix1[d[0]].copy() b = matrix2[d[0]].copy() c = matrix3[d[0]].copy() key_string = key.decode('utf-8') print("The key is: " + key_string) ``` Key:`REDchickenPIE` Flag:`grey{y0u_h4d_fun?_e4a3d}` ## Crackme3 Scirpt Dùng angr để giải: ``` import angr import claripy import logging #logging.getLogger('angr.sim_manager').('DEBUG') p = angr.Project("./crackme3", auto_load_libs = False) flag_chars = [claripy.BVS('flag_%d' % i, 8) for i in range(24)] flag = claripy.Concat( *flag_chars + [claripy.BVV(b'\n')]) st = p.factory.entry_state( args=['./crackme3'], add_options=angr.options.unicorn, stdin=flag ) sm = p.factory.simulation_manager(st) while True: #print(sm) sm.run(until=lambda sm_: len(sm_.active) > 1) for i in sm.active: i.add_constraints(i.mem[0x408184].uint16_t.resolved == 0) if len(sm.active) == 0: break print(sm) y = [] for x in sm.deadended: if b"Wrong" not in x.posix.dumps(1): y.append(x) print(y[0].posix.dumps(0)) ``` Flag: `grey{r_y0u_d1zzy?_9bfad}` # misc ## beepboop https://github.com/KMANVK/CTF_Wu/tree/main/Greycat%20CTF%20Quals%202023/Misc