# BKCTF
BabyStack
Nhìn tổng quan bài này yêu cầu ta nhập vào flag với độ dài là 20 ký tự, mình có thử nhập vào 1 chuỗi gồm 20 kí tự 'a' nhưng chương trình vẫn trả về như dưới đây

Tiến hành phân tích

Bài này sử dụng Stack VM, Stack VM là một dạng VM được thiết kế để thao tác các toán tử trên một ngăn xếp (stack) bằng việc đẩy vào (push), lấy ra (pop) và thao tác các toán tử trên stack. Sơ đồ sau đây sẽ mình họa về phép tính A*(B-C)+(D+E):
```
# stack contents (leftmost = top = added recently):
PUSH A: A
PUSH B: B A
PUSH C: C B A
SUB: (B-C) A
MUL: A*(B-C)
PUSH D: D A*(B-C)
PUSH E: E D A*(B-C)
ADD: (D+E) A*(B-C)
ADD: A*(B-C) + (D+E)
POP:
```
Các phần tử của phép toán được push vào trong stack, các phần tử có chức năng bằng nhau sẽ được tính toán thông qua các phép toán. Sau đó kết quả sẽ được pop ra, về cơ bản thì stack VM hoạt động như vậy
Sau khi vào bên trong ``stackVM::'vftable'`` nó có 1 số hàm, mình đọc và sửa lại tên hàm trông như sau:

Chương trình gồm 3 phần:
* Khởi tạo các bytecode cho VM

Sau khi nhập vào input, chương trình sẽ tiến hành chèn các input vào để thực hiện tính toán biến đổi

* Đánh giá các opcode

Ví dụ trong hình trên, chương trình sẽ kiểm xem opcode có phải là 6 hay không (ở đây rom[iter + 1] sẽ là các opcode). Nếu phải thì chương trình sẽ trích xuất thêm 2 phần tử rom[iter + 2] và rom[iter + 3], tạo một giá trị WORD từ 2 thông số này. Và từ đây cũng có thể dễ nhận thấy rằng riêng opcode 6 này có kích thước là 4 bytes, các opcode còn lại chỉ có kích thước 2 bytes.
Sau khi tìm đủ được đầy đủ các opcode, chương trình sẽ tiến hành thực thi các opcode đó:

Ở bước này, chương trình sẽ đưa vào `VM` các opcode để thực thi phần còn lại của chương trình
Mình có code 1 chương trình mô phỏng lại cách mà `VM` hoạt động:
```c=
#include <stdio.h>
#include <string.h>
void main(void)
{
int size, word, byte ;
int i = 0;
int op_code[400] = {
0x00, 0x06, 0x00, 0x01, 0x01, 0x06, 0x0C, 0x0D, 0x01, 0x06,
0x00, 0x08, 0x01, 0x05, 0x01, 0x06, 0x22, 0x38, 0x01, 0x06,
0xFF, 0x00, 0x01, 0x08, 0x01, 0x02, 0x01, 0x06, 0x62, 0x61,
0x01, 0x01, 0x01, 0x06, 0x69, 0x4E, 0x01, 0x00, 0x00, 0x07,
0x00, 0x00, 0x01, 0x06, 0x0C, 0x0D, 0x01, 0x06, 0x2D, 0x41,
0x01, 0x02, 0x01, 0x06, 0x00, 0x08, 0x01, 0x05, 0x01, 0x06,
0x22, 0x38, 0x01, 0x06, 0x55, 0x22, 0x01, 0x01, 0x01, 0x06,
0xFF, 0x00, 0x01, 0x08, 0x01, 0x02, 0x01, 0x06, 0x64, 0x63,
0x01, 0x01, 0x01, 0x06, 0x32, 0x6A, 0x01, 0x00, 0x00, 0x07,
0x00, 0x00, 0x01, 0x06, 0x49, 0x30, 0x01, 0x06, 0x00, 0x08,
0x01, 0x05, 0x01, 0x06, 0x3E, 0x5E, 0x01, 0x06, 0xFF, 0x00,
0x01, 0x08, 0x01, 0x02, 0x01, 0x06, 0x66, 0x65, 0x01, 0x01,
0x01, 0x06, 0x45, 0x0A, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00,
0x01, 0x06, 0x3B, 0x20, 0x01, 0x06, 0x00, 0x08, 0x01, 0x05,
0x01, 0x06, 0x6B, 0x2D, 0x01, 0x06, 0xFF, 0x00, 0x01, 0x08,
0x01, 0x02, 0x01, 0x06, 0x68, 0x67, 0x01, 0x01, 0x01, 0x06,
0x5B, 0x78, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x06,
0x2B, 0x79, 0x01, 0x06, 0x00, 0x08, 0x01, 0x05, 0x01, 0x06,
0x70, 0x41, 0x01, 0x06, 0xFF, 0x00, 0x01, 0x08, 0x01, 0x02,
0x01, 0x06, 0x6A, 0x69, 0x01, 0x01, 0x01, 0x06, 0x37, 0x45,
0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x78, 0x79,
0x01, 0x06, 0x00, 0x08, 0x01, 0x05, 0x01, 0x06, 0x34, 0x41,
0x01, 0x06, 0xFF, 0x00, 0x01, 0x08, 0x01, 0x02, 0x01, 0x06,
0x32, 0x31, 0x01, 0x01, 0x01, 0x06, 0x55, 0x0A, 0x01, 0x00,
0x00, 0x07, 0x00, 0x00, 0x01, 0x06, 0x6A, 0x36, 0x01, 0x06,
0x00, 0x08, 0x01, 0x05, 0x01, 0x06, 0x2D, 0x01, 0x01, 0x06,
0xFF, 0x00, 0x01, 0x08, 0x01, 0x02, 0x01, 0x06, 0x34, 0x33,
0x01, 0x01, 0x01, 0x06, 0x58, 0x1E, 0x01, 0x00, 0x00, 0x07,
0x00, 0x00, 0x01, 0x06, 0x75, 0x1B, 0x01, 0x06, 0x00, 0x08,
0x01, 0x05, 0x01, 0x06, 0x3B, 0x17, 0x01, 0x06, 0xFF, 0x00,
0x01, 0x08, 0x01, 0x02, 0x01, 0x06, 0x36, 0x35, 0x01, 0x01,
0x01, 0x06, 0x0F, 0x19, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00,
0x01, 0x06, 0x77, 0x7C, 0x01, 0x06, 0x00, 0x08, 0x01, 0x05,
0x01, 0x06, 0x45, 0x30, 0x01, 0x06, 0xFF, 0x00, 0x01, 0x08,
0x01, 0x02, 0x01, 0x06, 0x38, 0x37, 0x01, 0x01, 0x01, 0x06,
0x76, 0x03, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x01, 0x06,
0x0F, 0x37, 0x01, 0x06, 0x00, 0x08, 0x01, 0x04, 0x01, 0x06,
0x3B, 0x23, 0x01, 0x06, 0x00, 0xFF, 0x01, 0x08, 0x01, 0x02,
0x01, 0x06, 0x30, 0x39, 0x01, 0x01, 0x01, 0x06, 0x4A, 0x12,
0x01, 0x00, 0x00, 0x07, 0x00, 0x00
};
while(i<395)
{
size = 0;
word = -1;
byte = -1;
printf("0x%.4x ", i);
if(op_code[i + 1] == 6)
{
size = 4;
word = op_code[i + 3] + (op_code[i + 2] << 8);
byte = op_code[i];
}
else
{
size = 2;
byte = op_code[i];
}
switch(op_code[i + 1])
{
case 0:
printf("cmp");
break;
case 1:
printf("xor");
break;
case 2:
printf("add");
break;
case 3:
printf("sub");
break;
case 4:
printf("shl");
break;
case 5:
printf("shr");
break;
case 6:
printf("push 0x%.4x",word);
break;
case 7:
printf("pop");
break;
case 8:
printf("and");
break;
default:
printf("Invalid");
break;
}
i += size;
printf("\n");
}
return 0;
}
```
ở đây mình nhập vào sẽ là `abcdefghij1234567890`
kết quả sẽ trả ra đoạn code VM như sau
```
0x0000 push 0x0001
0x0004 push 0x0c0d
0x0008 push 0x0008
0x000c shr
0x000e push 0x2238
0x0012 push 0xff00
0x0016 and
0x0018 add
0x001a push 0x6261
0x001e xor
0x0020 push 0x694e
0x0024 cmp
0x0026 pop
0x0028 cmp
0x002a push 0x0c0d
0x002e push 0x2d41
```
Mình sẽ giải thích 1 đoạn VM ngắn như sau để mọi người có thể hiểu được
```
0x0000 push 0x0001
0x0004 push 0x0c0d
0x0008 push 0x0008
0x000c shr
0x000e push 0x2238
0x0012 push 0xff00
0x0016 and
0x0018 add
0x001a push 0x6261
0x001e xor
0x0020 push 0x694e
0x0024 cmp
0x0026 pop
0x0028 cmp
```
`VM` sẽ hoạt động như mô tả dưới đây:

1 cách dễ hiểu nhất thì chương trình sẽ load input mà ta nhập vào, sau đó thực hiện xor với cipher có sẵn rồi so sánh với 1 số cho trước. Như vậy ta chỉ cần lấy cipher rồi xor ngược lại với số được dùng để so sánh là xong.
Mình thử xor ngược `0x220c` và `0x694e` thì ra được 2 kí tự đầu tiên của flag

Tiếp tục làm như vậy 9 lần nữa ta sẽ ra được flag vì mỗi lần `VM` chạy sẽ duyệt 2 ký tự của input và flag có 20 ký tự. Ta sẽ có flag của challenge