---
# System prepended metadata

title: Writeups bi0sCTF 2024

---

#     **Writeups bi0sCTF 2024**
***
Cũng 5 tháng rồi từ lần cuối làm writeups nên nay quyết định làm một cái khởi đầu năm mới. Đợt này mình tham gia với team `TheRoundTable` và được hạng 21.
***
![image](https://hackmd.io/_uploads/BkvWMPj2T.png)
***
Trong thời gian giải mở thì mình làm được 2 bài bpf (đọc asm chay time), sau khi end giải thì mình có đi kiếm wu của bài `t0y-b0x` nhưng không một ai rep nên thôi tryhard tự làm luôn.
***
OKE giờ vào writeups nào!!!
***
## **1/BEEHIVE**
![image](https://hackmd.io/_uploads/BJueEwsh6.png)

***
### **REV**
Đề cho một file `ELF 64-bit LSB relocatable, eBPF` và mình chạy thử thì bị lỗi 
***
![image](https://hackmd.io/_uploads/rJ8oEDj2p.png)

***
Sau một hồi research thì mình kiếm được tool là `llvm-objdump` để dump code asm ra đọc.
***
![image](https://hackmd.io/_uploads/HJJzHvjhT.png)
***
Tới đây thì mình rev thuần chay thôi, việc kiếm tài liệu khá là mất nhiều thời gian vì trong bpf có một vài hàm gọi là `platform-agnostic helper functions` như có thể thấy ở dòng 14 có lệnh `call 4`, những hàm helper này sẽ không được giải thích ra dù sau đó mình đã cố tìm tool khác để xem nó có giải thích phần này không, nhưng các tool đều chỉ hiện lệnh asm là `call 4` mà thôi. Vì vậy mình đã tốn rất nhiều thời gian để tìm tài liệu về phần này. 

Đây là một số tài liệu để tham khảo:
* eBPF Instruction Set: `https://www.ietf.org/archive/id/draft-thaler-bpf-isa-00.html#platform-agnostic-helper-functions`
* BPF helper functions: `https://github.com/iovisor/bpf-docs/blob/master/bpf_helpers.rst/`

Bên trên là 2 tài liệu mình thấy có đầy đủ những gì mình cần để làm bài này, đặc biệt là phần helper functions mình không nhớ sao tìm được luôn nhưng bên trong nó sẽ không ghi rõ ứng với function nào thì bên asm sẽ call index nào. Mình đã rev hết flow của chương trình để biết được index 6 sẽ print chuỗi ra màn hình, vì vậy mình đã kiếm tài liệu nào có hàm print, tài liệu trên có hàm print được khai báo thứ 6, và như trong tài liệu cũng nêu ra
***
![image](https://hackmd.io/_uploads/S1yZKwo2p.png)
***

Đây là sau khi mình rev lại flow của chương trình.

```a!

beehive.o:	file format elf64-bpf

Disassembly of section raw_tracepoint/sys_enter:

0000000000000000 <weird_function>:
       0:	bf 13 00 00 00 00 00 00	r3 = r1
       1:	b7 01 00 00 00 00 00 00	r1 = 0
       2:	7b 1a f8 ff 00 00 00 00	*(u64 *)(r10 - 8) = r1
       3:	7b 1a f0 ff 00 00 00 00	*(u64 *)(r10 - 16) = r1
       4:	7b 1a e8 ff 00 00 00 00	*(u64 *)(r10 - 24) = r1
       5:	7b 1a e0 ff 00 00 00 00	*(u64 *)(r10 - 32) = r1
       6:	7b 1a d8 ff 00 00 00 00	*(u64 *)(r10 - 40) = r1
       7:	7b 1a d0 ff 00 00 00 00	*(u64 *)(r10 - 48) = r1
       8:	7b 1a c8 ff 00 00 00 00	*(u64 *)(r10 - 56) = r1
       9:	79 36 00 00 00 00 00 00	r6 = *(u64 *)(r3 + 0)
      10:	07 03 00 00 08 00 00 00	r3 += 8
      11:	bf a1 00 00 00 00 00 00	r1 = r10
      12:	07 01 00 00 c8 ff ff ff	r1 += -56
      13:	b7 02 00 00 08 00 00 00	r2 = 8
      14:	85 00 00 00 04 00 00 00	call MAYBE_READ_STORE_TO_R1_ADDRESS
      15:	79 a1 c8 ff 00 00 00 00	r1 = *(u64 *)(r10 - 56)
      16:	55 01 5f 00 37 13 03 00	if r1 != 201527 goto +95 <EXIT_FUCTION> ; *(u64 *)(r10 - 56) == 201527
      17:	bf 63 00 00 00 00 00 00	r3 = r6
      18:	07 03 00 00 70 00 00 00	r3 += 112
      19:	bf a1 00 00 00 00 00 00	r1 = r10
      20:	07 01 00 00 d0 ff ff ff	r1 += -48
      21:	b7 02 00 00 08 00 00 00	r2 = 8
      22:	85 00 00 00 04 00 00 00	call MAYBE_READ_STORE_TO_R1_ADDRESS
      23:	07 06 00 00 68 00 00 00	r6 += 104
      24:	bf a1 00 00 00 00 00 00	r1 = r10
      25:	07 01 00 00 d8 ff ff ff	r1 += -40
      26:	b7 02 00 00 08 00 00 00	r2 = 8
      27:	bf 63 00 00 00 00 00 00	r3 = r6
      28:	85 00 00 00 04 00 00 00	call MAYBE_READ_STORE_TO_R1_ADDRESS
      29:	79 a3 d0 ff 00 00 00 00	r3 = *(u64 *)(r10 - 48)
      30:	bf a6 00 00 00 00 00 00	r6 = r10
      31:	07 06 00 00 a8 ff ff ff	r6 += -88
      32:	bf 61 00 00 00 00 00 00	r1 = r6 ; address của buffer chứa input
      33:	b7 02 00 00 20 00 00 00	r2 = 32 
      34:	85 00 00 00 72 00 00 00	call 114 ; lười đếm để xác định đây là hàm gì cụ thể trong helpers nhưng đây là đang nhận input và lưu vào (r10-88)

      35:	18 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00	r1 = 0 ll ; 'Enter your key: %s'
      37:	b7 02 00 00 13 00 00 00	r2 = 19 ; len
      38:	bf 63 00 00 00 00 00 00	r3 = r6
      39:	85 00 00 00 06 00 00 00	call PRINT

      40:	71 a5 a8 ff 00 00 00 00	r5 = *(u8 *)(r10 - 88)
      41:	15 05 13 00 00 00 00 00	if r5 == 0 goto +19 <CORRECT>
      42:	b7 07 00 00 00 00 00 00	r7 = 0
      43:	b7 01 00 00 01 00 00 00	r1 = 1
      44:	18 02 00 00 14 00 00 00 00 00 00 00 00 00 00 00	r2 = 20 ll; khi gán biến r2 = 20 thêm 'll' là đang gán address ở .rodata index 20; lúc này đang trỏ vào ciphertext
      46:	b7 04 00 00 00 00 00 00	r4 = 0
      47:	b7 03 00 00 01 00 00 00	r3 = 1
      48:	b7 00 00 00 00 00 00 00	r0 = 0
      49:	05 00 0f 00 00 00 00 00	goto +15 <LBB0_3>

0000000000000190 <LBB0_13>:
      50:	07 02 00 00 04 00 00 00	r2 += 4 ; nhảy sang phần tử tiếp theo của ciphertext
      51:	bf a5 00 00 00 00 00 00	r5 = r10
      52:	07 05 00 00 a8 ff ff ff	r5 += -88
      53:	0f 15 00 00 00 00 00 00	r5 += r1 ; r1 là index đang được check tới
      54:	07 01 00 00 01 00 00 00	r1 += 1
      55:	71 55 00 00 00 00 00 00	r5 = *(u8 *)(r5 + 0); lấy value của element đang được trỏ tới trong input
      56:	bf 67 00 00 00 00 00 00	r7 = r6
      57:	55 05 07 00 00 00 00 00	if r5 != 0 goto +7 <LBB0_3>

00000000000001d0 <LBB0_14>:
      58:	67 03 00 00 20 00 00 00	r3 <<= 32
      59:	77 03 00 00 20 00 00 00	r3 >>= 32
      60:	15 03 2f 00 00 00 00 00	if r3 == 0 goto +47 <INCORRECT>

00000000000001e8 <CORRECT>:
      61:	18 01 00 00 88 00 00 00 00 00 00 00 00 00 00 00	r1 = 136 ll ; truy cập vào .rodata, phần nhớ ở 136 chính là 0x88 là chuỗi "Key is correct!"
      63:	b7 02 00 00 10 00 00 00	r2 = 16
      64:	05 00 2e 00 00 00 00 00	goto +46 <PRINT_FUCTION>

0000000000000208 <LBB0_3>:
      65:	bf 58 00 00 00 00 00 00	r8 = r5
      66:	b7 06 00 00 01 00 00 00	r6 = 1
      67:	15 08 01 00 40 00 00 00	if r8 == 64 goto +1 <LBB0_5>
      68:	bf 76 00 00 00 00 00 00	r6 = r7

0000000000000228 <LBB0_5>:
      69:	bf 68 00 00 00 00 00 00	r8 = r6
      70:	67 08 00 00 20 00 00 00	r8 <<= 32
      71:	77 08 00 00 20 00 00 00	r8 >>= 32
      72:	b7 07 00 00 01 00 00 00	r7 = 1
      73:	15 08 01 00 00 00 00 00	if r8 == 0 goto +1 <LBB0_7>
      74:	b7 07 00 00 00 00 00 00	r7 = 0

0000000000000258 <LBB0_7>:
      75:	b7 09 00 00 01 00 00 00	r9 = 1
      76:	55 08 01 00 00 00 00 00	if r8 != 0 goto +1 <LBB0_9>
      77:	b7 09 00 00 00 00 00 00	r9 = 0

0000000000000270 <LBB0_9>:
      78:	0f 94 00 00 00 00 00 00	r4 += r9
      79:	0f 70 00 00 00 00 00 00	r0 += r7
      80:	bf 47 00 00 00 00 00 00	r7 = r4
      81:	0f 07 00 00 00 00 00 00	r7 += r0
      82:	67 07 00 00 20 00 00 00	r7 <<= 32
      83:	77 07 00 00 20 00 00 00	r7 >>= 32
      84:	25 07 1b 00 20 00 00 00	if r7 > 32 goto +27 <EXIT_FUCTION>
      85:	15 01 e4 ff 1e 00 00 00	if r1 == 30 goto -28 <LBB0_14>
      86:	bf 57 00 00 00 00 00 00	r7 = r5 ; r7 = x
      87:	57 07 00 00 0f 00 00 00	r7 &= 15
      88:	67 07 00 00 04 00 00 00	r7 <<= 4 ; r7 = (x&15) << 4
      89:	57 05 00 00 f0 00 00 00	r5 &= 240; 
      90:	77 05 00 00 04 00 00 00	r5 >>= 4 ; r5 = (x&240) >> 4
      91:	4f 75 00 00 00 00 00 00	r5 |= r7 ; 
      92:	bf 57 00 00 00 00 00 00	r7 = r5 ; r7 = r5 = ((x&240) >> 4 | (x&15) << 4)
      93:	57 07 00 00 33 00 00 00	r7 &= 51; 
      94:	67 07 00 00 02 00 00 00	r7 <<= 2 ; r7 = (((x&240) >> 4 | (x&15) << 4)&51) << 2
      95:	77 05 00 00 02 00 00 00	r5 >>= 2
      96:	57 05 00 00 33 00 00 00	r5 &= 51 ; r5 = (((x&240) >> 4 | (x&15) << 4)>>2)&51
      97:	4f 75 00 00 00 00 00 00	r5 |= r7
      98:	bf 57 00 00 00 00 00 00	r7 = r5 ; r7 = r5 = (((((x&240) >> 4 | (x&15) << 4)>>2)&51) | ((((x&240) >> 4 | (x&15) << 4)&51) << 2))
      99:	57 07 00 00 55 00 00 00	r7 &= 85 
     100:	67 07 00 00 01 00 00 00	r7 <<= 1; r7 = (((((((x&240) >> 4 | (x&15) << 4)>>2)&51) | ((((x&240) >> 4 | (x&15) << 4)&51) << 2)))&=85)<<1
     101:	77 05 00 00 01 00 00 00	r5 >>= 1
     102:	57 05 00 00 55 00 00 00	r5 &= 85 ((((((x&240) >> 4 | (x&15) << 4)>>2)&51) | ((((x&240) >> 4 | (x&15) << 4)&51) << 2))>>1)&85
     103:	4f 75 00 00 00 00 00 00	r5 |= r7
     104:	61 27 00 00 00 00 00 00	r7 = *(u32 *)(r2 + 0) ; r7 lúc này là phần tử của ciphertext
     105:	1d 57 c8 ff 00 00 00 00	if r7 == r5 goto -56 <LBB0_13>
     106:	b7 03 00 00 00 00 00 00	r3 = 0
     107:	05 00 c6 ff 00 00 00 00	goto -58 <LBB0_13>

0000000000000360 <INCORRECT>:
     108:	18 01 00 00 98 00 00 00 00 00 00 00 00 00 00 00	r1 = 152 ll ; 'Key is incorrect!'
     110:	b7 02 00 00 12 00 00 00	r2 = 18 ; len

0000000000000378 <PRINT_FUCTION>:
     111:	85 00 00 00 06 00 00 00	call PRINT

0000000000000380 <EXIT_FUCTION>:
     112:	b7 00 00 00 00 00 00 00	r0 = 0
     113:	95 00 00 00 00 00 00 00	exit

Disassembly of section .relraw_tracepoint/sys_enter:

0000000000000000 <.relraw_tracepoint/sys_enter>:
       0:	18 01 00 00 00 00 00 00 
       1:   01 00 00 00 0f 00 00 00	
       2:	60 01 00 00 00 00 00 00	
       3:	01 00 00 00 0f 00 00 00	
       4:	e8 01 00 00 00 00 00 00	
       5:	01 00 00 00 0f 00 00 00	
       6:	60 03 00 00 00 00 00 00	
       7:	01 00 00 00 0f 00 00 00	

Disassembly of section .rodata:

0000000000000000 <weird_function.____fmt>:
       0:	45 6e 74 65 72 20 79 6f	
       1:	75 72 20 6b 65 79 3a 20	
       2:	25 73 00 00 56 00 00 00	
       3:	ae 00 00 00 ce 00 00 00	
       4:	ec 00 00 00 fa 00 00 00	
       5:	2c 00 00 00 76 00 00 00	
       6:	f6 00 00 00 2e 00 00 00	
       7:	16 00 00 00 cc 00 00 00	
       8:	4e 00 00 00 fa 00 00 00	
       9:	ae 00 00 00 ce 00 00 00	
      10:	cc 00 00 00 4e 00 00 00	
      11:	76 00 00 00 2c 00 00 00	
      12:	b6 00 00 00 a6 00 00 00	
      13:	02 00 00 00 46 00 00 00	
      14:	96 00 00 00 0c 00 00 00	
      15:	ce 00 00 00 74 00 00 00	
      16:	96 00 00 00 76 00 00 00	

0000000000000088 <weird_function.____fmt.1>:
      17:	4b 65 79 20 69 73 20 63	
      18:	6f 72 72 65 63 74 21 00	

0000000000000098 <weird_function.____fmt.2>:
      19:	4b 65 79 20 69 73 20 69	
      20:	6e 63 6f 72 72 65 63 74	
      21:	21	
      21:	00	
```
***

Phần encrypt input có nhiều phép toán quá nên mình bruteforce luôn
***
### **SOL**
```python=
a = bytes.fromhex('56aeceecfa2c76f62e16cc4efaaececc4e762cb6a60246960cce749676')
flag = ""

for i in (a):
    for x in range(33,127):
        if (((((((x&240) >> 4 | (x&15) << 4)>>2)&51) | ((((x&240) >> 4 | (x&15) << 4)&51) << 2))>>1)&85) | ((((((((x&240) >> 4 | (x&15) << 4)>>2)&51) | ((((x&240) >> 4 | (x&15) << 4)&51) << 2)))&85)<<1) == i:
            flag+=chr(x)
            break
        
print(len(flag))
print(f"bi0sctf{{{flag}}}")
```
***
### **FLAG** 
**`bi0sctf{jus7_4noth3r_us3rn4me@bi0s.in}`**
***
## **2/BAEBPF**
![image](https://hackmd.io/_uploads/ryOH0voh6.png)
***
Đọc chay bài đầu quen rồi nên sang bài này mình thấy đọc nhanh hơn tí.
***
### **REV**
![image](https://hackmd.io/_uploads/r1E20Di2a.png)
***
Nếu chọn dump assembly thì ta nhận được flow của chương trình. Rev lại đống đó thì hẵng qua cat file.
***
Ngoài assembly dump thì ta sẽ có thêm cả map dump

![image](https://hackmd.io/_uploads/rkwGyOjnp.png)
***
Code asm của phần này rất dễ, chỉ là check tên file muốn đọc, phần password chỉ là phép xor với 5.
***
![image](https://hackmd.io/_uploads/SJXkgOihT.png)
![image](https://hackmd.io/_uploads/HJpygOona.png)
***
Tiếp tục chọn 1 để dump code asm ra rev.

Đây là code mình đã rev thay đổi một số thứ nên sẽ khác với code được dump ra.

```a!
void encrypt_function():
   0: (bf) r6 = r10
   1: (07) r6 += -4
   2: (18) mask = 0xffffffe0
   4: (b7) r8 = 0 ; uint32_t v[2] = {0,0};

   5: (b7) r1 = 0
   6: (7b) *(u64 *)(r10 -8) = r1
   7: (63) *(u32 *)(r10 -12) = r8 ; uint32_t *temp = bpf_map_lookup_elem((void *)bpf_pseudo_fd(1, -1), &index);
   8: (18) r1 = map[id:14]
  10: (bf) delta = r10
  11: (07) delta += -12 ; uint32_t *temp = bpf_map_lookup_elem((void *)bpf_pseudo_fd(1, -1), &index);
  12: (07) r1 += 272
  13: (61) r0 = *(u32 *)(delta +0)
  14: (35) if r0 >= 0x400 goto pc+3
  15: (67) r0 <<= 3
  16: (0f) r0 += r1
  17: (05) goto pc+1
  18: (b7) r0 = 0
  19: (bf) r7 = r0 ; if (temp != NULL && *temp != 0)
  20: (15) if r7 == 0x0 goto pc+78
  21: (61) r1 = *(u32 *)(r7 +0)
  22: (15) if r1 == 0x0 goto pc+76
  23: (63) *(u32 *)(r10 -8) = r1 ; uint32_t *temp2 = bpf_map_lookup_elem((void *)bpf_pseudo_fd(1, -2), &index);
  24: (18) r1 = map[id:13]
  26: (bf) delta = r10
  27: (07) delta += -12 ; uint32_t *temp2 = bpf_map_lookup_elem((void *)bpf_pseudo_fd(1, -2), &index);
  28: (07) r1 += 272
  29: (61) r0 = *(u32 *)(delta +0)
  30: (35) if r0 >= 0x400 goto pc+3
  31: (67) r0 <<= 3
  32: (0f) r0 += r1
  33: (05) goto pc+1
  34: (b7) r0 = 0
  35: (15) if r0 == 0x0 goto pc+63
  36: (61) r1 = *(u32 *)(r7 +0)
  37: (15) if r1 == 0x0 goto pc+61
  
  38: (b7) r1 = 32
  39: (18) delta = 0x9e3779b9
  41: (61) r7 = *(u32 *)(r10 -8)
  42: (61) r4 = *(u32 *)(r0 +0) ; v[0]
  
  43: (63) *(u32 *)(r10 -4) = r4
  44: (bf) r3 = r4  
  45: (67) r3 <<= 4
  46: (07) r3 += key  ((r3<<4)+key)^(r3+0x9e3779b9)
  47: (bf) r5 = r4
  48: (0f) r5 += delta
  49: (af) r3 ^= r5
  50: (bf) r5 = r4  
  51: (5f) r5 &= mask
  52: (77) r5 >>= 5  
  53: (07) r5 += key
  54: (af) r3 ^= r5       (((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))
  55: (0f) r3 += r7
  56: (bf) r5 = r3           ((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)
  57: (67) r5 <<= 4
  58: (07) r5 += key  (((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)<<4)+key
  59: (bf) r0 = delta
  60: (0f) r0 += r3          ((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7) + 0x9e3779b9
  61: (af) r5 ^= r0   ((((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)<<4)+key ) ^ (((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7) + 0x9e3779b9)
  62: (bf) r0 = r3
  63: (5f) r0 &= mask
  64: (77) r0 >>= 5
  65: (07) r0 += key     (((((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)&0xffffffe0)>>5)+key)
  66: (af) r5 ^= r0
  67: (0f) r5 += r4             (((((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)<<4)+key ) ^ (((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7) + 0x9e3779b9))^ (((((((r3 & 0xffffffe0)>>5)+key)^(((r3<<4)+key)^(r3+0x9e3779b9))+ r7)&0xffffffe0)>>5)+key) + r3
  68: (07) delta += -1640531527
  69: (07) r1 += -1
  70: (bf) r0 = r1
  71: (67) r0 <<= 32
  72: (77) r0 >>= 32
  73: (bf) r4 = r5
  74: (bf) r7 = r3
  75: (15) if r0 == 0x0 goto pc+1
  76: (05) goto pc-33
  77: (63) *(u32 *)(r10 -4) = r5
  78: (63) *(u32 *)(r10 -8) = r3 ; bpf_map_update_elem((void *)bpf_pseudo_fd(1, -3), &index,&v[0], BPF_ANY);
  79: (18) r1 = map[id:12]
  81: (bf) r7 = r10
  82: (07) r7 += -12
  83: (bf) r3 = r10
  84: (07) r3 += -8 ; bpf_map_update_elem((void *)bpf_pseudo_fd(1, -3), &index,&v[0], BPF_ANY);
  85: (bf) delta = r7
  86: (b7) r4 = 0
  87: (85) call array_map_update_elem#296464 ; bpf_map_update_elem((void *)bpf_pseudo_fd(1, -4), &index,&v[1], BPF_ANY);
  88: (18) r1 = map[id:11] ; bpf_map_update_elem((void *)bpf_pseudo_fd(1, -4), &index,&v[1], BPF_ANY);
  90: (bf) delta = r7
  91: (bf) r3 = r6
  92: (b7) r4 = 0
  93: (85) call array_map_update_elem#296464
  94: (07) r8 += 1
  95: (bf) r1 = r8
  96: (67) r1 <<= 32
  97: (77) r1 >>= 32
  98: (55) if r1 != 0x80 goto pc-94
  99: (95) exit
```
***
Thì đây chỉ là phép mã hóa TEA mà thôi. Mình mất hơn nửa ngày để tìm cách implement lại trên python từ các phép tính có trong asm dump nhưng mà không được. Mình định sủi giải thì anh `@jinn` nói code bằng c đi.

![image](https://hackmd.io/_uploads/HyNr-ui2a.png)
![image](https://hackmd.io/_uploads/rytUZOo3p.png)
***
### **SOL LV2**
Lúc này mình đang nằm ngủ trưa mới dậy thấy tin nhắn liền thử leo lên máy kiếm code implement của tea thử. 

```c=
#include <stdio.h>
#include <stdint.h>

uint32_t KEY[4] = {305402420,305402420,305402420,305402420};  // Key space for bit shifts

void encrypt(uint32_t* v) {
  uint32_t v0=v[0], v1=v[1], sum=0, i;             // set up
  uint32_t delta=0x9e3779b9;                       // a key schedule constant
  for (i=0; i < 32; i++) {                         // basic cycle start
    sum += delta;
    v0 += ((v1<<4) + KEY[0]) ^ (v1 + sum) ^ ((v1>>5) + KEY[1]);
    v1 += ((v0<<4) + KEY[2]) ^ (v0 + sum) ^ ((v0>>5) + KEY[3]);  
  }                                                // end cycle 
  v[0]=v0; v[1]=v1;
}       

void decrypt (uint32_t* v) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  // set up 
    uint32_t delta=0x9e3779b9;                     // a key schedule constant 
    for (i=0; i<32; i++) {                         // basic cycle start 
        v1 -= ((v0<<4) + KEY[2]) ^ (v0 + sum) ^ ((v0>>5) + KEY[3]);
        v0 -= ((v1<<4) + KEY[0]) ^ (v1 + sum) ^ ((v1>>5) + KEY[1]);
        sum -= delta;
    }                                              // end cycle 
    v[0]=v0; v[1]=v1;
}

int main()
{       
    uint32_t enc[] = {0x33ae2685,0x230bcdd5,0x4f5ac093,0x3dc3e00a,0xda19d0a1,0x32c52ad0,0xc904ffac,0x3037b842,0x9c7bf31e,0x4b8dfebc,0x33335ba7,0x4c4c9188,0xa555d9a9,0xaa069852,0xa177367f,0x79daa10f,0x29ca035c,0x319fbbc8,0xd51b4a1c,0x4a1b63b6,0x99f5d2f1,0xf35fdd82,0x7e70314f,0x42077d00,0x4f84cb2b,0x4a73846a,0xbbb0581e,0x8c33c34f,0x4eb73143,0xac45de0,0x82592087,0xc02544fa,0x56590be4,0xd2f78e08,0xb2c9d125,0x65e106d8,0x46711844,0xcf16ec7f,0xc85dde46,0x51d873d,0x50319f0f,0x8e5370bd,0x80145a76,0xbdbe90a6,0x3a10947e,0xfaf968c7,0xac700a03,0x47e061be,0xe9e65b90,0xe3c65a80,0xd707d969,0x40e93f77,0x447cf10e,0xbc69c7df,0xd8c669de,0x36c05ccf,0x876411ba,0xb37a6436,0xcdbeac33,0x7ba23db9,0xc18251bd,0x926d7a16,0x9ffb0134,0xc7f9ab96,0xc635711e,0x45b69a8,0x7b0fdd2e,0xf54849a7,0x61e5d839,0x1f12687d,0xb39a4ba1,0xd4fa2f5a,0xc308a7fd,0xcc0f199b,0x6b35768,0xecb39e48,0xb2c9d125,0x65e106d8,0x9e9a0f73,0xc58bdf39,0xa9bb76d1,0xc75ccd7,0x8473c66,0x8a4ed0e5,0xae1dcf9a,0x214f0ed5,0xfb6bf695,0x56e45cc6,0x47e4e2b9,0x8e2107d1,0x5a24b1dc,0x70599ee2,0x6cd313ec,0x4fa221e8,0x6696e856,0x62fde305,0x79958e01,0x1b99f294,0x876fd3a,0x59c1d749,0x0,0x0};
		for (int i = 0; i <= 99; i = i+2) {
            uint32_t v[] = {enc[i], enc[i+1]};
            decrypt(v);
            printf("%X%X", v[0], v[1]);
        }
        return 0;
}
```

Key ở đây là 305402420, nếu diễn giải đống asm trên sẽ thấy từng vị trí khớp với algo của TEA.

![image](https://hackmd.io/_uploads/rJzWG_in6.png)

***

Chạy sẽ được một chuỗi hex rất dài. Mình nhìn đã thấy sú sú không thể là flag được. Đổi ra thì lại được một chương trình python.

![image](https://hackmd.io/_uploads/SyKuzdjh6.png)
![image](https://hackmd.io/_uploads/SJr9zOi36.png)
***
### **SOL LV3**
Chương trình chỉ đơn giản là in flag thôi nhưng do phải qua hàm reccur nên sẽ mất rất nhiều thời gian. Tới đây mình cho lưu lại vào một mảng hết.

```python=
arr = [[x,0] for x in range(10000)]

def reccur(i): 
     if(not i):
         arr[i][1] = 1
        #  return 1
     if(i == 1):
         arr[i][1] = 3
        #  return  3
     if arr[i][1] == 0:
        val_2 = 2 *reccur(i-1)
        res = val_2 + 3* reccur(i-2) 
        arr[i][1] = res
     return arr[i][1]
    #  exit() 
enc_flag = [102,75,163,239,156,158,7,143,92,120,0,54,183,65,199,253,60,182,204] 
dec_flag = ""
for i in range(19):
    flag_val = enc_flag[i]
    ctr_val = reccur((i * i)+1)% 256
    val = flag_val ^ ctr_val 
    dec_flag += chr(val)

print(f"bi0sctf{{{dec_flag}}}")
```
***
![image](https://hackmd.io/_uploads/BJu3Vdjh6.png)
***
### **FLAG**
**`bi0sctf{eBPF_wtF_1s_th4t???}`**
***
## **3/T0Y-B0X**

![image](https://hackmd.io/_uploads/HylnFr_s3T.png)

(đã rev còn thêm quả tag `Cryptography` trôn vl)
***
Bài này thì sau giải mình làm lại do hỏi sol script trong server nhưng không được trả lời. Với đang mò một vài cái hay ho, dù mấy cái đó không áp dụng được trong bài này nhưng yeah mình thấy rất vui. Mình sẽ không đề cập trong đây mà tập trung về việc giải bài này.
***
### **REV**

Đề cho mình 2 file, file thực thi chall và một file chứa ciphertext. Nhìn thấy 2 file này kèm với tag `Crytography` thì mình biết phải đi tìm cách input bị encrypt rồi đi decrypt lại ciphertext.

![image](https://hackmd.io/_uploads/Syw0I_j3p.png)
***

Chạy thử file chall thì nhận của mình 2 input. 

![image](https://hackmd.io/_uploads/B1jew_sna.png)
***

Ngó qua hàm main

```c=
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  void *v3; // rsp
  void *v4; // rsp
  __int64 *v5; // rax
  __int64 v6; // rdx
  char **v8; // [rsp+0h] [rbp-8D0h] BYREF
  int v9; // [rsp+Ch] [rbp-8C4h]
  int i; // [rsp+1Ch] [rbp-8B4h]
  int j; // [rsp+20h] [rbp-8B0h]
  int v12; // [rsp+24h] [rbp-8ACh]
  unsigned int v13; // [rsp+28h] [rbp-8A8h]
  int v14; // [rsp+2Ch] [rbp-8A4h]
  int v15; // [rsp+30h] [rbp-8A0h]
  int v16; // [rsp+34h] [rbp-89Ch]
  int v17; // [rsp+38h] [rbp-898h]
  int c; // [rsp+3Ch] [rbp-894h]
  __int64 v19; // [rsp+40h] [rbp-890h]
  char ***v20; // [rsp+48h] [rbp-888h]
  void *src; // [rsp+50h] [rbp-880h]
  void *v22; // [rsp+58h] [rbp-878h]
  __int64 v23; // [rsp+60h] [rbp-870h]
  void *dest; // [rsp+68h] [rbp-868h]
  __int64 v25[2]; // [rsp+70h] [rbp-860h] BYREF
  char v26[16]; // [rsp+80h] [rbp-850h] BYREF
  char s[32]; // [rsp+90h] [rbp-840h] BYREF
  char v28[1024]; // [rsp+B0h] [rbp-820h] BYREF
  char v29[1032]; // [rsp+4B0h] [rbp-420h] BYREF
  unsigned __int64 v30; // [rsp+8B8h] [rbp-18h]

  v9 = a1;
  v8 = a2;
  v30 = __readfsqword(0x28u);
  v12 = 176;
  v19 = 175LL;
  v3 = alloca(176LL);
  v20 = &v8;
  __isoc99_scanf("%[^\n]16s", v28);
  __isoc99_scanf("%1024s", v29);
  v13 = 16;
  src = (void *)sub_125F("%1024s", v29);
  sub_27E7(v20, v28, v13, v12);
  qmemcpy(s, "[yb2zg5w7k|yiyi$", 16);
  s[16] = 15;
  memcpy(&unk_60E0, src, 0x400uLL);
  if ( dword_60C0 )
  {
    v22 = malloc(0x400uLL);
    sub_12CA(v22);
    memcpy(&unk_60E0, v22, 0x400uLL);
  }
  sub_22EB(s);
  v14 = strlen(s);
  v15 = strlen(v29);
  v16 = (v15 + v14) / 16 + 1;
  v17 = 16 * v16;
  v23 = 16 * v16 - 1LL;
  v4 = alloca(16 * ((16 * v16 + 15LL) / 0x10uLL));
  dest = &v8;
  memcpy(&v8, s, v14);
  memcpy((char *)dest + v14, v29, v15);
  c = v17 - v14 - v15;
  memset((char *)dest + v15 + (__int64)v14, c, c);
  for ( i = 0; i < v16; ++i )
  {
    v5 = (__int64 *)((char *)dest + 16 * i);
    v6 = v5[1];
    v25[0] = *v5;
    v25[1] = v6;
    sub_2F85(v25, v26, v28, 16LL);
    for ( j = 0; j <= 15; ++j )
      printf("%2.2x", (unsigned __int8)v26[j]);
  }
  putchar(10);
  return 0LL;
}
```

Nếu đi sâu vào các hàm con thì sẽ thấy gọi thêm nhiều hàm khác nữa. 
Và sau khi tryhard + research thì mình đã reverse lại tất cả các hàm cũng như flow bài.

```c=
__int64 __fastcall main(int a1, char **a2, char **a3)
{
  void *v3; // rsp
  void *v4; // rsp
  __int64 *v5; // rax
  __int64 v6; // rdx
  void *dest_; // [rsp+0h] [rbp-8D0h] BYREF
  int v9; // [rsp+Ch] [rbp-8C4h]
  int i; // [rsp+1Ch] [rbp-8B4h]
  int j; // [rsp+20h] [rbp-8B0h]
  int v12; // [rsp+24h] [rbp-8ACh]
  unsigned int v13; // [rsp+28h] [rbp-8A8h]
  int LEN_S; // [rsp+2Ch] [rbp-8A4h]
  int LEN_SECOND; // [rsp+30h] [rbp-8A0h]
  int v16; // [rsp+34h] [rbp-89Ch]
  int v17; // [rsp+38h] [rbp-898h]
  int c; // [rsp+3Ch] [rbp-894h]
  __int64 v19; // [rsp+40h] [rbp-890h]
  void **ptr; // [rsp+48h] [rbp-888h]
  void *src; // [rsp+50h] [rbp-880h]
  void *fake_; // [rsp+58h] [rbp-878h]
  __int64 v23; // [rsp+60h] [rbp-870h]
  void *dest; // [rsp+68h] [rbp-868h]
  __int64 v25[2]; // [rsp+70h] [rbp-860h] BYREF
  char res[16]; // [rsp+80h] [rbp-850h] BYREF
  char LOOKLIKE_IV[32]; // [rsp+90h] [rbp-840h] BYREF
  char key[1024]; // [rsp+B0h] [rbp-820h] BYREF
  char PLAINTEXT[1032]; // [rsp+4B0h] [rbp-420h] BYREF
  unsigned __int64 v30; // [rsp+8B8h] [rbp-18h]

  v9 = a1;
  dest_ = a2;
  v30 = __readfsqword(0x28u);
  v12 = 0xB0;
  v19 = 175LL;
  v3 = alloca(176LL);
  ptr = &dest_;
  __isoc99_scanf("%[^\n]16s", key);
  __isoc99_scanf("%1024s", PLAINTEXT);
  v13 = 16;
  src = CREATE_255_ARRAY("%1024s");
  expand_key((__int64)ptr, (__int64)key, v13, v12);
  qmemcpy(LOOKLIKE_IV, "[yb2zg5w7k|yiyi$", 16);
  LOOKLIKE_IV[16] = 0xF;
  memcpy(SBOX, src, sizeof(SBOX));
  if ( debug_flag )
  {
    fake_ = malloc(0x400uLL);
    FAKE_ARRAY(fake_);
    memcpy(SBOX, fake_, sizeof(SBOX));
  }
  XOR((__int64)LOOKLIKE_IV);
  LEN_S = strlen(LOOKLIKE_IV);
  LEN_SECOND = strlen(PLAINTEXT);
  v16 = (LEN_SECOND + LEN_S) / 16 + 1;
  v17 = 16 * v16;
  v23 = 16 * v16 - 1LL;
  v4 = alloca(16 * ((16 * v16 + 15LL) / 0x10uLL));
  dest = &dest_;
  memcpy(&dest_, LOOKLIKE_IV, LEN_S);
  memcpy((char *)dest + LEN_S, PLAINTEXT, LEN_SECOND);
  c = v17 - LEN_S - LEN_SECOND;
  memset((char *)dest + LEN_SECOND + (__int64)LEN_S, c, c);
  for ( i = 0; i < v16; ++i )
  {
    v5 = (__int64 *)((char *)dest + 16 * i);
    v6 = v5[1];
    v25[0] = *v5;
    v25[1] = v6;
    AES((__int64)v25, (__int64)res, (__int64)key, 0x10u);
    for ( j = 0; j <= 15; ++j )
      printf("%2.2x", (unsigned __int8)res[j]);
  }
  putchar(10);
  return 0LL;
}
```

Tóm tắt qua bài này đi thì đây là một bài sử dụng mã hóa AES mod ECB nhưng với SBOX là mảng các phần tử từ 0 đến 255. Vì cái SBOX này nên mình thực sự tốn nhiều thời gian để giải quyết nó. Cơ bản mình không rành gì về mấy thuật toán mã hóa, nhưng sau bài này cũng nắm sơ về AES. 

Nếu để ý trên code mình rev lại thì chuỗi s ở dòng 43 đã được mình rename lại thành `LOOKLIKE_IV`. Và ye đó là một lỗi sai ngớ ngẩn của mình khi làm bài này. Mình bắt đầu ngồi rev lúc cả nhóm mới học xong và ghé quán cafe trường ngồi nghỉ, nên thời gian làm cũng không có nhiêu. 

Vì vậy mình đã không debug mà đọc sơ qua code, đọc sơ xong nhầm key thành IV luôn. Thực chất chuỗi s đó là key. Vì nhầm lẫn nên mình tưởng đây là một bài AES sử dụng mode CBC. 

![image](https://hackmd.io/_uploads/SyPCdFi2a.png)


Tới lúc rev lại tất cả các hàm của bài thì mình nhận ra không có đoạn nào xor IV với cả block data cả. Vì vậy mới debug kĩ thì thấy đây là mode ECB. Nhưng mode nào cũng không quan trọng vì đồng đội crypto của mình `@tranminhprvt01` đã kiếm được một paper rất hay để giải quyết vấn đề dễ dàng.

Vậy nói sơ qua về flow bài:
* Nhận 2 input 
* Input 1 chính là key
* Input 2 là plaintext
* Khởi tạo SBOX = [0x00, 0x01,..., 0xff]
* Check anti-debug (cái này tác giả đã viết hàm check ptrace bằng asm dạng gọi syscall và còn đặt trong initarray nên không để ý sẽ không biết đây là flag check debug vì ban đầu flag này khai báo là 1 và 1 nghĩa là đang debug, qua hàm check debug nếu không debug nó sẽ trở thành 0 nên dễ nghĩ điều kiện 1 trong if là dĩ nhiên)
* Nếu bị phát hiện debug thì SBOX đổi thành một mảng khác.
* Sau khi chuỗi `LOOKLIKE_IV` qua hàm xor sẽ thành chuỗi `Tis is a secret:`, thôi gọi đây là chuỗi s nhá, mình sẽ còn đề cập tới chuỗi này.
* dest sẽ chứa: 16 byte mảng s + plaintext
* Sau đó qua hàm AES (ECB) encrypt rồi in ra thôi

Lúc làm bài với teammate mình đã thử lấy chuỗi s làm input đầu vì mình thấy nó khá là sú. Và đúng thật s chính là key.

![image](https://hackmd.io/_uploads/Byclp_j26.png)

Đến lúc này thì mình đã biết rõ chương trình làm gì rồi. Ta đã có key và ciphertext, việc còn lại chỉ cần decrypt ra flag mà thôi.
***
Việc tìm code implement aes để decrypt rất mất thời gian...
***

Do lúc làm bài này mình muốn tự làm thật kĩ và làm hết nên mình tự đi kiếm code implement của aes, nhưng như đã nói ở trên. Lúc đầu mình nhầm nó là aes cbc 256 nên đi kiếm code mãi mà không được. Tới tối mình mới biết nó là ECB 128 bit, cũng thử kiếm code nhưng cái khó là thằng SBOX. 

Mình không biết làm sao để tính được inverse của thằng SBOX đặc biệt này. Trong lúc mình đang ngồi search cách tính inv SBOX thì teammate crypto của mình `@tranminhprvt01` đã kiếm dược một trang nói về vấn đề này.

![image](https://hackmd.io/_uploads/HyzY0OihT.png)

***
Cũng ra gì đấy, chuẩn vấn đề mình đang gặp luôn >:0
***
### **SOL**
Đào vô sâu thì đã có một người đưa ra giải pháp cho vấn đề này. Cơ bản thì sau khi thay thế SBOX mới, nếu ta thay plaintext đầu vào bằng các giá trị 0 thì ta sẽ nhận được một mảng gọi là `equivalent_key`...(Chắc chờ cryptomate giải thích phần này rồi bổ sung writeup sau, mình không thực sự hiểu rõ cách làm này lắm nên không dám múa rìu qua mắt thợ)

![image](https://hackmd.io/_uploads/rJAR0Oon6.png)

Vào POC của họ lấy code về thì để thử decrypt với key đã tìm được thì...

![image](https://hackmd.io/_uploads/SJQrBKo26.png)

***
Update giải thích súc tích của cryptomate.

![image](https://hackmd.io/_uploads/BkZx8to3p.png)

***
### **FLAG**
**`bi0sctf{L1n34rly_Un5huffl3d_T0y5}`**