# vmcode.exe
chall: [vmcode.exe](https://drive.google.com/file/d/1P9RfqTukVk67EQfmEeQKv-evMPM0kE4E/view?usp=sharing)
Mở ida và check hàm `main`
đầu tiên chương trình khởi tạo một loạt các giá trị truyền `v9` và sau đó thực thi hàm `vm` và chạy hàm `run`

kiểm tra hàm `vm`:

tạo struct để `Thiss` để dễ đọc `this` hơn
(tạo struct: shift+ F1 -> chuột phải -> insert)
(struct được tạo bằng cách xem `this` gồm tìm có bao nhiêu phần từ với kiểu dữ liệu là gì và đọc code để biết chức năng nó làm gì (cái nào chưa biết chức năng thì để tên là `this` còn biết được chức năng sau khi đọc code thì đổi tên để dễ đọc hơn ạ))
```c=
struct Thiss
{
DWORD this0;
DWORD this1;
DWORD this2;
DWORD this3;
DWORD stepp;
DWORD this5;
DWORD is0x100_6;
DWORD is0x300_7;
DWORD this8;
DWORD this9;
DWORD vmcode;
DWORD this11;
func function[48];
};
```
với func:
```c=
struct func
{
DWORD instruction_name; // tên lệnh
WORD step;
DWORD instruction_offset; //offset của lênh
BYTE jumpp; //nếu có nhảy vào một địa chỉ nào đó hay return thì có giá trị = 1
};
```
để đọc `this` với struct mới tạo (chuột phải `this` -> convert to struct * -> `Thiss` mới tạo )
code mới trông như thế này:

sau khi khởi tạo các giá trị của `this` chương trình thư thi hàm `sub_401590` hàm này là thuật toán `RC4` với đầu vào là key = 'KMACTF' đề cho và `step` của function trên :

Debug tới đoạn đã qua hàm `RC4` và in ra giá trị mới của `function`
```
function = [['MOVI', '0x4b7', 7488, 0], ['MOVR', '0x24e', 7552, 0], ['LODI', '0x4dc', 7648, 0], ['LODR', '0x267', 7728, 0], ['STRI', '0x496', 7840, 0], ['STRR', '0x20c', 7920, 0], ['ADDI', '0x428', 8032, 0], ['ADDR', '0x26a', 8096, 0], ['SUBI', '0x4fb', 8192, 0], ['SUBR', '0x2ff', 8256, 0], ['ANDB', '0x35d', 8352, 0], ['ANDW', '0x46c', 8432, 0], ['ANDR', '0x22e', 8496, 0], ['YORB', '0x35f', 8592, 0], ['YORW', '0x40b', 8672, 0], ['YORR', '0x263', 8736, 0], ['XORB', '0x357', 8832, 0], ['XORW', '0x401', 8912, 0], ['XORR', '0x229', 8976, 0], ['NOTR', '0x24a', 9072, 0], ['MULI', '0x48f', 9168, 0], ['MULR', '0x225', 9248, 0], ['DIVI', '0x472', 9344, 0], ['DIVR', '0x283', 9440, 0], ['SHLI', '0x439', 9552, 0], ['SHLR', '0x29f', 9616, 0], ['SHRI', '0x4fa', 9712, 0], ['SHRR', '0x258', 9776, 0], ['PUSH', '0x23e', 9872, 0], ['POOP', '0x210', 9968, 0], ['CMPB', '0x359', 10048, 0], ['CMPW', '0x40f', 10144, 0], ['CMPR', '0x255', 10240, 0], ['JMPI', '0x305', 10368, 1], ['JMPR', '0x2ab', 10400, 1], ['JPAI', '0x314', 10464, 1], ['JPAR', '0x24f', 10512, 1], ['JPBI', '0x354', 10576, 1], ['JPBR', '0x2bd', 10624, 1], ['JPEI', '0x327', 10688, 1], ['JPER', '0x20d', 10736, 1], ['JPNI', '0x318', 10800, 1], ['JPNR', '0x287', 10848, 1], ['CALL', '0x31d', 10912, 1], ['RETN', '0x1f9', 11008, 1], ['SHIT', '0x1ce', 11040, 0], ['NOPE', '0x150', 11088, 0], ['GRMN', '0x134', 11056, 0]]
```
dùng idapython với `addr` là địa chỉ của `this`:
```python=
addr = 0x004FF510
funcs = []
addr = addr + 0x4 *12
for i in range(48):
a = addr + i*0x10
func = []
func.append(bytes.fromhex(format(get_wide_dword(get_wide_dword(a)), 'x')).decode('utf-8')[::-1])
func.append(get_wide_byte(a + 4))
funcs.append(func)
print(funcs)
```

Với hàm `run`:

hàm này đọc vmcode (là các giá trị `v9`ở đầu bài) để biết được vmcode tương ứng với các lệnh nào
từ hàm `run` và các hàm gọi tới chức năng của các lệnh thì viết đoạn disassembly như sau:
```python=
vm = [0xdc, 0x0, 0x0, 0x0, 0x28, 0x0, 0xbd, 0x3, 0xf, 0x0, 0x13, 0x51, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x2, 0x0, 0xb7, 0x2, 0x2e, 0x0, 0x29, 0x2, 0xf, 0x0, 0x6d, 0x30, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x4, 0x0, 0xb7, 0x2, 0xb, 0x0, 0x29, 0x2, 0xf, 0x0, 0x6f, 0x33, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x6, 0x0, 0x28, 0x0, 0x69, 0x3, 0xf, 0x0, 0xc8, 0x34, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x8, 0x0, 0xb7, 0x2, 0x2b, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x57, 0x0, 0x29, 0x2, 0xf, 0x0, 0xf, 0x5f, 0x18, 0x33, 0x1, 0xdc, 0x0, 0xa, 0x0, 0xb7, 0x2, 0x61, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x61, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x40, 0x0, 0x29, 0x2, 0xf, 0x0, 0x23, 0x68, 0x18, 0x33, 0x1, 0xdc, 0x0, 0xc, 0x0, 0xfb, 0x0, 0x4f, 0x3, 0xf, 0x0, 0xe5, 0x2d, 0x18, 0x33, 0x1, 0xdc, 0x0, 0xe, 0x0, 0xb7, 0x2, 0x46, 0x0, 0x29, 0x2, 0xf, 0x0, 0x77, 0x33, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x10, 0x0, 0xb7, 0x2, 0x1f, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x1c, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x26, 0x0, 0x29, 0x2, 0xf, 0x0, 0x4b, 0x39, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x12, 0x0, 0xb7, 0x2, 0xf, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x57, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x3f, 0x0, 0x29, 0x2, 0xf, 0x0, 0x54, 0x5f, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x14, 0x0, 0xb7, 0x2, 0x37, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x58, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x4c, 0x0, 0x29, 0x2, 0xf, 0x0, 0x41, 0x31, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x16, 0x0, 0xb7, 0x2, 0x24, 0x0, 0x29, 0x2, 0xf, 0x0, 0x1d, 0x5f, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x18, 0x0, 0xb7, 0x2, 0x1a, 0x0, 0x29, 0x2, 0xb7, 0x2, 0x1c, 0x0, 0x29, 0x2, 0xf, 0x0, 0x6e, 0x34, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x1a, 0x0, 0xfb, 0x0, 0x80, 0x3, 0xf, 0x0, 0xee, 0x60, 0x18, 0x33, 0x1, 0xdc, 0x0, 0x1c, 0x0, 0xfb, 0x0, 0x9, 0x1, 0xf, 0x0, 0x6a, 0x20, 0x18, 0x33, 0x1, 0x34, 0xce, 0x50, 0xce,0,0,0]
function = [['MOVI', 0x4b7, 7488, 0], ['MOVR', 0x24e, 7552, 0], ['LODI', 0x4dc, 7648, 0], ['LODR', 0x267, 7728, 0], ['STRI', 0x496, 7840, 0], ['STRR', 0x20c, 7920, 0], ['ADDI', 0x428, 8032, 0], ['ADDR', 0x26a, 8096, 0], ['SUBI', 0x4fb, 8192, 0], ['SUBR', 0x2ff, 8256, 0], ['ANDB', 0x35d, 8352, 0], ['ANDW', 0x46c, 8432, 0], ['ANDR', 0x22e, 8496, 0], ['YORB', 0x35f, 8592, 0], ['YORW', 0x40b, 8672, 0], ['YORR', 0x263, 8736, 0], ['XORB', 0x357, 8832, 0], ['XORW', 0x401, 8912, 0], ['XORR', 0x229, 8976, 0], ['NOTR', 0x24a, 9072, 0], ['MULI', 0x48f, 9168, 0], ['MULR', 0x225, 9248, 0], ['DIVI', 0x472, 9344, 0], ['DIVR', 0x283, 9440, 0], ['SHLI', 0x439, 9552, 0], ['SHLR', 0x29f, 9616, 0], ['SHRI', 0x4fa, 9712, 0], ['SHRR', 0x258, 9776, 0], ['PUSH', 0x23e, 9872, 0], ['POOP', 0x210, 9968, 0], ['CMPB', 0x359, 10048, 0], ['CMPW', 0x40f, 10144, 0], ['CMPR', 0x255, 10240, 0], ['JMPI', 0x305, 10368, 1], ['JMPR', 0x2ab, 10400, 1], ['JPAI', 0x314, 10464, 1], ['JPAR', 0x24f, 10512, 1], ['JPBI', 0x354, 10576, 1], ['JPBR', 0x2bd, 10624, 1], ['JPEI', 0x327, 10688, 1], ['JPER', 0x20d, 10736, 1], ['JPNI', 0x318, 10800, 1], ['JPNR', 0x287, 10848, 1], ['CALL', 0x31d, 10912, 1], ['RETN', 0x1f9, 11008, 1], ['SHIT', 0x1ce, 11040, 0], ['NOPE', 0x150, 11088, 0], ['GRMN', 0x134, 11056, 0]]
def run(this):
res = []
stepp = 0
while 1:
cnt = 0
while cnt != 48:
if vm[stepp] == this[cnt][1]& 0xff:
res = this[cnt]
break
cnt += 1
if res[0] in ['LODI','LODR','JMPI','JMPR','JPAI','JPAR','JPBI','JPBR','JPEI','JPER','JPNI','JPNR','CALL','RETN','SHIT','NOPE','GRMN','XORB','XORW','XORR']:
print(res[0])
else:
print(res[0]+ " " + hex(vm[stepp + 2 + 1] * 0x100 + vm[stepp+ 2]))
if res[0] == 'JPNI':
print()
stepp += 3
elif res[0] == 'GRMN': #với 'GRMN' là print "That's it" là cái cần tìm rồi nên dừng lại
break
if res[3] == 0:
stepp += res[1] >> 8
run(function)
```
> đoạn code asm cần tìm là:
```
LODI
ADDI 0x3bd
CMPW 0x5113
JPNI
LODI
MOVI 0x2e
XORR
CMPW 0x306d
JPNI
LODI
MOVI 0xb
XORR
CMPW 0x336f
JPNI
LODI
ADDI 0x369
CMPW 0x34c8
JPNI
LODI
MOVI 0x2b
XORR
MOVI 0x57
XORR
CMPW 0x5f0f
JPNI
LODI
MOVI 0x61
XORR
MOVI 0x61
XORR
MOVI 0x40
XORR
CMPW 0x6823
JPNI
LODI
SUBI 0x34f
CMPW 0x2de5
JPNI
LODI
MOVI 0x46
XORR
CMPW 0x3377
JPNI
LODI
MOVI 0x1f
XORR
MOVI 0x1c
XORR
MOVI 0x26
XORR
CMPW 0x394b
JPNI
LODI
MOVI 0xf
XORR
MOVI 0x57
XORR
MOVI 0x3f
XORR
CMPW 0x5f54
JPNI
LODI
MOVI 0x37
XORR
MOVI 0x58
XORR
MOVI 0x4c
XORR
CMPW 0x3141
JPNI
LODI
MOVI 0x24
XORR
CMPW 0x5f1d
JPNI
LODI
MOVI 0x1a
XORR
MOVI 0x1c
XORR
CMPW 0x346e
JPNI
LODI
SUBI 0x380
CMPW 0x60ee
JPNI
LODI
SUBI 0x109
CMPW 0x206a
JPNI
GRMN
```
từ code trên tìm từ giá trị khi gọi `LODI` vào để bằng với giá trị khi `CMPW`
ví dụ:
```
LODI
SUBI 0x109
CMPW 0x206a
JPNI
-> giá trị cần tìm = bytes.fromhex(format(0x206a + 0x109, 'x')).decode('utf-8')[::-1]
#'s!'
```
-> Vậy input cần tìm là:
'VMC0d3_1s_ch4113n93_b19_h4nds!'
> flag: "VMC0d3_1s_ch4113n93_b19_h4nds!"