---
# System prepended metadata

title: Grey Cat The Flag 2023 Qualifiers

---

# 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
