---
# System prepended metadata

title: MiniVM

---

# MiniVM

![image](https://hackmd.io/_uploads/Hy3Yit8v-l.png)

Bài cho ta 1 file thực thi .exe .Thử mở nó lên bằng DiE để xem qua profile

![image](https://hackmd.io/_uploads/B1i8D2Iw-l.png)

1 file được viết bằng Go và ở section .zdebug_line có dấu hiệu bị packed. Nhưng sau khi search thì có vẻ như việc section debug info của Go bị nén như vậy là bình thường :v Tiếp tục thực thi file để xem hành vi

![image](https://hackmd.io/_uploads/BJ4Ud2UD-x.png)

Vẫn là 1 dạng check flag thôi, nhưng nhìn qua thì khả năng bài này còn check cả len của input ,dựa vào thông báo nó in ra

Mở lên bằng IDA để xem pseudocode
```c 
// main.main
void __fastcall main_main()
{
  __int128 v0; // xmm15
  __int64 v1; // rsi
  __int64 v2; // rcx
  __int64 v3; // r8
  int v4; // r9d
  int v5; // r10d
  int v6; // r11d
  __int64 n10; // r9
  __int64 v8; // rdx
  __int64 os.Stdout; // rbx
  __int64 v10; // rax
  __int64 v11; // rcx
  int v12; // r8d
  int v13; // r9d
  int v14; // r10d
  int v15; // r11d
  __int64 v16; // rax
  __int64 v17; // rcx
  int String; // eax
  int v19; // ecx
  int v20; // r8d
  int v21; // r9d
  int v22; // r10d
  int v23; // r11d
  __int64 v24; // rax
  void *v25; // rdx
  int v26; // r11d
  __int64 n60; // r9
  int v28; // r8d
  int v29; // r9d
  int v30; // r10d
  int v31; // r11d
  int v32; // eax
  int v33; // ecx
  int v34; // r8d
  int v35; // r9d
  int v36; // r10d
  int v37; // r11d
  __int64 v38; // rax
  __int64 v39; // [rsp+10h] [rbp-2A0h]
  __int64 v40; // [rsp+10h] [rbp-2A0h]
  __int64 v41; // [rsp+18h] [rbp-298h]
  __int64 v42; // [rsp+18h] [rbp-298h]
  __int64 v43; // [rsp+20h] [rbp-290h]
  int v44; // [rsp+48h] [rbp-268h]
  _QWORD v45[2]; // [rsp+50h] [rbp-260h] BYREF
  __int128 v46; // [rsp+60h] [rbp-250h] BYREF
  _QWORD v47[2]; // [rsp+70h] [rbp-240h] BYREF
  _QWORD v48[2]; // [rsp+80h] [rbp-230h] BYREF
  void *p_p_runtime.noptrbss[2]; // [rsp+90h] [rbp-220h] BYREF
  _BYTE v50[40]; // [rsp+1B0h] [rbp-100h] BYREF
  __int128 v51; // [rsp+1D8h] [rbp-D8h] BYREF
  __int64 n4096; // [rsp+1E8h] [rbp-C8h]
  RTYPE **go:itab._os.File_io.Reader; // [rsp+1F0h] [rbp-C0h]
  __int64 runtime.bss_1; // [rsp+1F8h] [rbp-B8h]
  _QWORD v55[5]; // [rsp+208h] [rbp-A8h] BYREF
  _OWORD v56[5]; // [rsp+230h] [rbp-80h] BYREF
  _QWORD v57[2]; // [rsp+288h] [rbp-28h] BYREF
  _QWORD v58[2]; // [rsp+298h] [rbp-18h] BYREF
  __int64 runtime.bss; // [rsp+2A8h] [rbp-8h]

  v58[0] = &RTYPE_string;
  v58[1] = &off_1400F1710;
  v1 = 1;
  fmt_Fprintln((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v58, 1, 1);
  if ( qword_140182DC8 <= 1 )
  {
    v57[0] = &RTYPE_string;
    v57[1] = &off_1400F1720;
    os.Stdout = os_Stdout;
    v10 = fmt_Fprint((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v57, 1, 1, v3, v4, v5, v6);
    runtime.bss = runtime_bss;
    v56[0] = v0;
    ((void (__golang *)(__int64, __int64, __int64, _QWORD *))loc_140072470)(v10, os.Stdout, v11, v55);
    v16 = runtime_makeslice((unsigned int)&RTYPE_uint8, 4096, 4096, (unsigned int)v55, 1, v12, v13, v14, v15);
    v51 = v0;
    *(_QWORD *)&v51 = ((__int64 (__golang *)(__int64, __int64, __int64, _BYTE *))loc_140072470)(v16, 4096, v17, v50);
    *((_QWORD *)&v51 + 1) = 4096;
    n4096 = 4096;
    go:itab._os.File_io.Reader = go_itab__os_File_io_Reader;
    runtime.bss_1 = runtime.bss;
    v55[3] = -1;
    v55[4] = -1;
    *(_QWORD *)&v56[0] = v51;
    v1 = (__int64)&v51 + 8;
    ((void (__fastcall *)(char *, char *))loc_1400727DA)((char *)v56 + 8, (char *)&v51 + 8);
    String = bufio__ptr_Reader_ReadString(v56, 10);
    v24 = strings_TrimSpace(String, 10, v19, (unsigned int)v56 + 8, (unsigned int)&v51 + 8, v20, v21, v22, v23);
    n10 = 10;
    v8 = v24;
  }
  else
  {
    n10 = *(_QWORD *)(os_Args + 24);
    v8 = *(_QWORD *)(os_Args + 16);
  }
  p_p_runtime.noptrbss[1] = *((void **)&v0 + 1);
  ((void (__fastcall *)(void **, __int64, __int64, __int64, __int64, __int64))loc_14007241D)(
    &p_p_runtime.noptrbss[1],
    v1,
    v8,
    v2,
    v3,
    n10);
  p_p_runtime.noptrbss[0] = &runtime_noptrbss;
  v50[0] = 1;
  v50[32] = 1;
  if ( n60 == 60 )
  {
    v44 = (int)v25;
    if ( (unsigned __int8)main__ptr_MiniVM_execute(
                            p_p_runtime.noptrbss,
                            main_BYTECODE,
                            *(unsigned __int64 *)&qword_14017A9C8,
                            *(__int64 *)&qword_14017A9D0,
                            v25,
                            60,
                            60,
                            &runtime_noptrbss,
                            v26) )
    {
      v47[0] = &RTYPE_string;
      v47[1] = &off_1400F1740;                  // "\n[+] Congratulations! You found the flag!34694469519536141888238489627838134765625"
      fmt_Fprintln((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v47, 1, 1);
      v46 = v0;
      v32 = runtime_concatstring2(
              0,
              (unsigned int)"[+] Flag is correct: ",
              21,
              v44,
              60,
              v28,
              v29,
              v30,
              v31,
              v39,
              v41,
              v43);
      v38 = runtime_convTstring(v32, (unsigned int)"[+] Flag is correct: ", v33, v44, 60, v34, v35, v36, v37, v40, v42);
      *(_QWORD *)&v46 = &RTYPE_string;
      *((_QWORD *)&v46 + 1) = v38;
      fmt_Fprintln((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)&v46, 1, 1);
    }
    else
    {
      v45[0] = &RTYPE_string;
      v45[1] = &off_1400F1750;                  // "\n[-] Wrong flag! Try again..."
      fmt_Fprintln((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v45, 1, 1);
    }
  }
  else
  {
    v48[0] = &RTYPE_string;
    v48[1] = &off_1400F1730;                    // "\n[-] Wrong flag length!"
    fmt_Fprintln((unsigned int)go_itab__os_File_io_Writer, os_Stdout, (unsigned int)v48, 1, 1);
  }
}
```
Đầu tiên mình sẽ làm rõ về việc check len, phần thông báo in ra ```Wrong flag length!``` ở trong nhánh else của chương trình, khi nhìn lên nhánh if thì thấy điều kiện `n60 == 60`, ở đây có thể đoán luôn là `len` == 60. Kiểm tra bằng cách điền 60bytes rác vào
![image](https://hackmd.io/_uploads/Bki8ohUwZl.png)

Ok vậy đúng là `len` = 60 rồi


### Ta sẽ xác định xem VM nằm ở đâu trong GO binary bằng cách liệt kê symbol
```bash
(base) ┌──(venv-pwn)(hieesu19㉿DESKTOP-BFB0MA5)-[/mnt/d/CTF/ATTT_PTIT/re/MiniVM/MiniVM]
└─$ go tool nm mini_vm.exe | grep -E "main\."
140175b60 D go:main.inittasks
1400a1980 T main.(*MiniVM).execute
14017a9c0 D main.BYTECODE
1400a23c0 T main.main
1400673a0 T runtime.main.func1
14003da00 T runtime.main.func2
```
=> VM chính là `main.(*MiniVM).execute`, còn chương trình VM nằm trong `main.BYTECODE`

### Tiếp theo ta sẽ rev lại `main.main` để hiểu rõ flow check flag
Ta cần disasm nó
```asm
└─$ go tool objdump -s "main\.main" mini_vm.exe
TEXT main.main(SB) C:/Users/toanv/OneDrive/Desktop/Challenge/Chall2/mini_vm.go
  mini_vm.go:190        0x1400a23c0             4c8da424d8fdffff                LEAQ 0xfffffdd8(SP), R12
  mini_vm.go:190        0x1400a23c8             4d3b6610                        CMPQ R12, 0x10(R14)
  mini_vm.go:190        0x1400a23cc             0f8672030000                    JBE 0x1400a2744
  mini_vm.go:190        0x1400a23d2             55                              PUSHQ BP
  mini_vm.go:190        0x1400a23d3             4889e5                          MOVQ SP, BP
  mini_vm.go:190        0x1400a23d6             4881eca0020000                  SUBQ $0x2a0, SP
  mini_vm.go:191        0x1400a23dd             488d159cb10000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:191        0x1400a23e4             4889942488020000                MOVQ DX, 0x288(SP)
  mini_vm.go:191        0x1400a23ec             488d151df30400                  LEAQ runtime.buildVersion.str+16(SB), DX
  mini_vm.go:191        0x1400a23f3             4889942490020000                MOVQ DX, 0x290(SP)
  print.go:314          0x1400a23fb             488b1d26060e00                  MOVQ os.Stdout(SB), BX
  print.go:314          0x1400a2402             488d05cff90400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:314          0x1400a2409             488d8c2488020000                LEAQ 0x288(SP), CX
  print.go:314          0x1400a2411             bf01000000                      MOVL $0x1, DI
  print.go:314          0x1400a2416             4889fe                          MOVQ DI, SI
  print.go:314          0x1400a2419             e822a4ffff                      CALL fmt.Fprintln(SB)
  mini_vm.go:201        0x1400a241e             48833da2090e0001                CMPQ os.Args+8(SB), $0x1
  mini_vm.go:201        0x1400a2426             7e14                            JLE 0x1400a243c
  mini_vm.go:201        0x1400a2428             488b1591090e00                  MOVQ os.Args(SB), DX
  mini_vm.go:202        0x1400a242f             4c8b4a18                        MOVQ 0x18(DX), R9
  mini_vm.go:202        0x1400a2433             488b5210                        MOVQ 0x10(DX), DX
  mini_vm.go:202        0x1400a2437             e95e010000                      JMP 0x1400a259a
  mini_vm.go:204        0x1400a243c             488d153db10000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:204        0x1400a2443             4889942478020000                MOVQ DX, 0x278(SP)
  mini_vm.go:204        0x1400a244b             488d15cef20400                  LEAQ runtime.buildVersion.str+32(SB), DX
  mini_vm.go:204        0x1400a2452             4889942480020000                MOVQ DX, 0x280(SP)
  print.go:272          0x1400a245a             488b1dc7050e00                  MOVQ os.Stdout(SB), BX
  print.go:272          0x1400a2461             488d0570f90400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:272          0x1400a2468             488d8c2478020000                LEAQ 0x278(SP), CX
  print.go:272          0x1400a2470             bf01000000                      MOVL $0x1, DI
  print.go:272          0x1400a2475             4889fe                          MOVQ DI, SI
  print.go:272          0x1400a2478             e8e3a2ffff                      CALL fmt.Fprint(SB)
  mini_vm.go:205        0x1400a247d             488b159c050e00                  MOVQ runtime.bss(SB), DX
  mini_vm.go:205        0x1400a2484             4889942498020000                MOVQ DX, 0x298(SP)
  bufio.go:63           0x1400a248c             90                              NOPL
  bufio.go:56           0x1400a248d             440f11bc2420020000              MOVUPS X15, 0x220(SP)
  bufio.go:56           0x1400a2496             488dbc2428020000                LEAQ 0x228(SP), DI
  bufio.go:56           0x1400a249e             488d7fd0                        LEAQ -0x30(DI), DI
  bufio.go:56           0x1400a24a2             48896c24f0                      MOVQ BP, -0x10(SP)
  bufio.go:56           0x1400a24a7             488d6c24f0                      LEAQ -0x10(SP), BP
  bufio.go:56           0x1400a24ac             e8bffffcff                      CALL 0x140072470
  bufio.go:56           0x1400a24b1             488b6d00                        MOVQ 0(BP), BP
  bufio.go:57           0x1400a24b5             488d0544b10000                  LEAQ type:*+42496(SB), AX
  bufio.go:57           0x1400a24bc             bb00100000                      MOVL $0x1000, BX
  bufio.go:57           0x1400a24c1             4889d9                          MOVQ BX, CX
  bufio.go:57           0x1400a24c4             e8579dfcff                      CALL runtime.makeslice(SB)
  bufio.go:88           0x1400a24c9             440f11bc24c8010000              MOVUPS X15, 0x1c8(SP)
  bufio.go:88           0x1400a24d2             488dbc24d0010000                LEAQ 0x1d0(SP), DI
  bufio.go:88           0x1400a24da             488d7fd0                        LEAQ -0x30(DI), DI
  bufio.go:88           0x1400a24de             6690                            NOPW
  bufio.go:88           0x1400a24e0             48896c24f0                      MOVQ BP, -0x10(SP)
  bufio.go:88           0x1400a24e5             488d6c24f0                      LEAQ -0x10(SP), BP
  bufio.go:88           0x1400a24ea             e881fffcff                      CALL 0x140072470
  bufio.go:88           0x1400a24ef             488b6d00                        MOVQ 0(BP), BP
  bufio.go:89           0x1400a24f3             48898424c8010000                MOVQ AX, 0x1c8(SP)
  bufio.go:89           0x1400a24fb             48c78424d001000000100000        MOVQ $0x1000, 0x1d0(SP)
  bufio.go:89           0x1400a2507             48c78424d801000000100000        MOVQ $0x1000, 0x1d8(SP)
  bufio.go:90           0x1400a2513             488d159ef80400                  LEAQ go:itab.*os.File,io.Reader(SB), DX
  bufio.go:90           0x1400a251a             48899424e0010000                MOVQ DX, 0x1e0(SP)
  bufio.go:90           0x1400a2522             488b942498020000                MOVQ 0x298(SP), DX
  bufio.go:90           0x1400a252a             48899424e8010000                MOVQ DX, 0x1e8(SP)
  bufio.go:91           0x1400a2532             48c7842410020000ffffffff        MOVQ $-0x1, 0x210(SP)
  bufio.go:92           0x1400a253e             48c7842418020000ffffffff        MOVQ $-0x1, 0x218(SP)
  bufio.go:88           0x1400a254a             488b9424c8010000                MOVQ 0x1c8(SP), DX
  bufio.go:88           0x1400a2552             4889942420020000                MOVQ DX, 0x220(SP)
  bufio.go:88           0x1400a255a             488dbc2428020000                LEAQ 0x228(SP), DI
  bufio.go:88           0x1400a2562             488db424d0010000                LEAQ 0x1d0(SP), SI
  bufio.go:88           0x1400a256a             48896c24f0                      MOVQ BP, -0x10(SP)
  bufio.go:88           0x1400a256f             488d6c24f0                      LEAQ -0x10(SP), BP
  bufio.go:88           0x1400a2574             e86102fdff                      CALL 0x1400727da
  bufio.go:88           0x1400a2579             488b6d00                        MOVQ 0(BP), BP
  mini_vm.go:206        0x1400a257d             488d842420020000                LEAQ 0x220(SP), AX
  mini_vm.go:206        0x1400a2585             bb0a000000                      MOVL $0xa, BX
  mini_vm.go:206        0x1400a258a             e891a5fdff                      CALL bufio.(*Reader).ReadString(SB)
  mini_vm.go:207        0x1400a258f             e8ac9dfdff                      CALL strings.TrimSpace(SB)
  mini_vm.go:212        0x1400a2594             4989d9                          MOVQ BX, R9
  mini_vm.go:212        0x1400a2597             4889c2                          MOVQ AX, DX
  mini_vm.go:210        0x1400a259a             90                              NOPL
  mini_vm.go:21         0x1400a259b             440f11bc2480000000              MOVUPS X15, 0x80(SP)
  mini_vm.go:21         0x1400a25a4             488dbc2488000000                LEAQ 0x88(SP), DI
  mini_vm.go:21         0x1400a25ac             48896c24f0                      MOVQ BP, -0x10(SP)
  mini_vm.go:21         0x1400a25b1             488d6c24f0                      LEAQ -0x10(SP), BP
  mini_vm.go:21         0x1400a25b6             e862fefcff                      CALL 0x14007241d
  mini_vm.go:21         0x1400a25bb             488b6d00                        MOVQ 0(BP), BP
  mini_vm.go:22         0x1400a25bf             4c8d157a5b1200                  LEAQ runtime.zerobase(SB), R10
  mini_vm.go:22         0x1400a25c6             4c89942480000000                MOVQ R10, 0x80(SP)
  mini_vm.go:23         0x1400a25ce             c68424a001000001                MOVB $0x1, 0x1a0(SP)
  mini_vm.go:24         0x1400a25d6             c68424c001000001                MOVB $0x1, 0x1c0(SP)
  mini_vm.go:24         0x1400a25de             6690                            NOPW
  mini_vm.go:212        0x1400a25e0             4983f93c                        CMPQ R9, $0x3c
  mini_vm.go:212        0x1400a25e4             0f8519010000                    JNE 0x1400a2703
  mini_vm.go:212        0x1400a25ea             4c894c2430                      MOVQ R9, 0x30(SP)
  mini_vm.go:212        0x1400a25ef             4889542438                      MOVQ DX, 0x38(SP)
  mini_vm.go:217        0x1400a25f4             488b1dc5830d00                  MOVQ main.BYTECODE(SB), BX
  mini_vm.go:217        0x1400a25fb             488b0dc6830d00                  MOVQ main.BYTECODE+8(SB), CX
  mini_vm.go:217        0x1400a2602             488b3dc7830d00                  MOVQ main.BYTECODE+16(SB), DI
  mini_vm.go:217        0x1400a2609             488d842480000000                LEAQ 0x80(SP), AX
  mini_vm.go:217        0x1400a2611             4889d6                          MOVQ DX, SI
  mini_vm.go:217        0x1400a2614             4d89c8                          MOVQ R9, R8
  mini_vm.go:217        0x1400a2617             e864f3ffff                      CALL main.(*MiniVM).execute(SB)
  mini_vm.go:217        0x1400a261c             0f1f4000                        NOPL 0(AX)
  mini_vm.go:217        0x1400a2620             84c0                            TESTL AL, AL
  mini_vm.go:219        0x1400a2622             0f849a000000                    JE 0x1400a26c2
  mini_vm.go:220        0x1400a2628             488d1551af0000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:220        0x1400a262f             4889542460                      MOVQ DX, 0x60(SP)
  mini_vm.go:220        0x1400a2634             488d1505f10400                  LEAQ runtime.buildVersion.str+64(SB), DX
  mini_vm.go:220        0x1400a263b             4889542468                      MOVQ DX, 0x68(SP)
  print.go:314          0x1400a2640             488b1de1030e00                  MOVQ os.Stdout(SB), BX
  print.go:314          0x1400a2647             488d058af70400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:314          0x1400a264e             488d4c2460                      LEAQ 0x60(SP), CX
  print.go:314          0x1400a2653             bf01000000                      MOVL $0x1, DI
  print.go:314          0x1400a2658             4889fe                          MOVQ DI, SI
  print.go:314          0x1400a265b             0f1f440000                      NOPL 0(AX)(AX*1)
  print.go:314          0x1400a2660             e8dba1ffff                      CALL fmt.Fprintln(SB)
  mini_vm.go:221        0x1400a2665             440f117c2450                    MOVUPS X15, 0x50(SP)
  mini_vm.go:221        0x1400a266b             31c0                            XORL AX, AX
  mini_vm.go:221        0x1400a266d             488d1dfc8d0200                  LEAQ go:string.*+13720(SB), BX
  mini_vm.go:221        0x1400a2674             b915000000                      MOVL $0x15, CX
  mini_vm.go:221        0x1400a2679             488b7c2438                      MOVQ 0x38(SP), DI
  mini_vm.go:221        0x1400a267e             488b742430                      MOVQ 0x30(SP), SI
  mini_vm.go:221        0x1400a2683             e8181bfbff                      CALL runtime.concatstring2(SB)
  mini_vm.go:221        0x1400a2688             e85375fcff                      CALL runtime.convTstring(SB)
  mini_vm.go:221        0x1400a268d             488d15ecae0000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:221        0x1400a2694             4889542450                      MOVQ DX, 0x50(SP)
  mini_vm.go:221        0x1400a2699             4889442458                      MOVQ AX, 0x58(SP)
  print.go:314          0x1400a269e             488b1d83030e00                  MOVQ os.Stdout(SB), BX
  print.go:314          0x1400a26a5             488d052cf70400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:314          0x1400a26ac             488d4c2450                      LEAQ 0x50(SP), CX
  print.go:314          0x1400a26b1             bf01000000                      MOVL $0x1, DI
  print.go:314          0x1400a26b6             4889fe                          MOVQ DI, SI
  print.go:314          0x1400a26b9             e882a1ffff                      CALL fmt.Fprintln(SB)
  print.go:314          0x1400a26be             6690                            NOPW
  mini_vm.go:225        0x1400a26c0             eb38                            JMP 0x1400a26fa
  mini_vm.go:223        0x1400a26c2             488d15b7ae0000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:223        0x1400a26c9             4889542440                      MOVQ DX, 0x40(SP)
  mini_vm.go:223        0x1400a26ce             488d157bf00400                  LEAQ runtime.buildVersion.str+80(SB), DX
  mini_vm.go:223        0x1400a26d5             4889542448                      MOVQ DX, 0x48(SP)
  print.go:314          0x1400a26da             488b1d47030e00                  MOVQ os.Stdout(SB), BX
  print.go:314          0x1400a26e1             488d05f0f60400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:314          0x1400a26e8             488d4c2440                      LEAQ 0x40(SP), CX
  print.go:314          0x1400a26ed             bf01000000                      MOVL $0x1, DI
  print.go:314          0x1400a26f2             4889fe                          MOVQ DI, SI
  print.go:314          0x1400a26f5             e846a1ffff                      CALL fmt.Fprintln(SB)
  mini_vm.go:225        0x1400a26fa             4881c4a0020000                  ADDQ $0x2a0, SP
  mini_vm.go:225        0x1400a2701             5d                              POPQ BP
  mini_vm.go:225        0x1400a2702             c3                              RET
  mini_vm.go:213        0x1400a2703             488d1576ae0000                  LEAQ type:*+42368(SB), DX
  mini_vm.go:213        0x1400a270a             4889542470                      MOVQ DX, 0x70(SP)
  mini_vm.go:213        0x1400a270f             488d151af00400                  LEAQ runtime.buildVersion.str+48(SB), DX
  mini_vm.go:213        0x1400a2716             4889542478                      MOVQ DX, 0x78(SP)
  print.go:314          0x1400a271b             488b1d06030e00                  MOVQ os.Stdout(SB), BX
  print.go:314          0x1400a2722             488d05aff60400                  LEAQ go:itab.*os.File,io.Writer(SB), AX
  print.go:314          0x1400a2729             488d4c2470                      LEAQ 0x70(SP), CX
  print.go:314          0x1400a272e             bf01000000                      MOVL $0x1, DI
  print.go:314          0x1400a2733             4889fe                          MOVQ DI, SI
  print.go:314          0x1400a2736             e805a1ffff                      CALL fmt.Fprintln(SB)
  mini_vm.go:214        0x1400a273b             4881c4a0020000                  ADDQ $0x2a0, SP
  mini_vm.go:214        0x1400a2742             5d                              POPQ BP
  mini_vm.go:214        0x1400a2743             c3                              RET
  mini_vm.go:190        0x1400a2744             e8b7d7fcff                      CALL runtime.morestack_noctxt.abi0(SB)
  mini_vm.go:190        0x1400a2749             e972fcffff                      JMP main.main(SB)
  :-1                   0x1400a274e             cc                              INT $0x3
  :-1                   0x1400a274f             cc                              INT $0x3
  :-1                   0x1400a2750             cc                              INT $0x3
  :-1                   0x1400a2751             cc                              INT $0x3
  :-1                   0x1400a2752             cc                              INT $0x3
  :-1                   0x1400a2753             cc                              INT $0x3
  :-1                   0x1400a2754             cc                              INT $0x3
  :-1                   0x1400a2755             cc                              INT $0x3
  :-1                   0x1400a2756             cc                              INT $0x3
  :-1                   0x1400a2757             cc                              INT $0x3
  :-1                   0x1400a2758             cc                              INT $0x3
  :-1                   0x1400a2759             cc                              INT $0x3
  :-1                   0x1400a275a             cc                              INT $0x3
  :-1                   0x1400a275b             cc                              INT $0x3
  :-1                   0x1400a275c             cc                              INT $0x3
  :-1                   0x1400a275d             cc                              INT $0x3
  :-1                   0x1400a275e             cc                              INT $0x3
  :-1                   0x1400a275f             cc                              INT $0x3
```

Flow sẽ là : 
- in ra`Enter the flag`
- đọc input
- Check len(flag) == 60 (nếu sai thì in thông báo và thoát)
- tạo vm, gọi vm.execute(BYTECODE, flag)
- in ra  correct / wrong

=> cần tìm điều kiện để execute() trả về true

### rev lại miniVM để hiểu nó làm gì

`go tool objdump -s "main\.\(\*MiniVM\)\.execute" mini_vm.exe > execute.asm`

[execute.asm](https://ideone.com/7TudVL)

dùng GPT để đọc 
![image](https://hackmd.io/_uploads/BJtlo6vDZl.png)



### extract bytecode từ binary
Ta sẽ lấy địa chỉ của `main.BYTECODE`

```bash 
└─$ go tool nm mini_vm.exe | grep -i BYTECODE
14017a9c0 D main.BYTECODE
```

Tiếp đó ta cần đổi VA sang file offset bằng section ``.data`
```bash
└─$ objdump -h mini_vm.exe

mini_vm.exe:     file format pei-x86-64

Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         000a1791  0000000140001000  0000000140001000  00000600  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .rdata        000d18c8  00000001400a3000  00000001400a3000  000a1e00  2**4
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .data         0000dc00  0000000140175000  0000000140175000  00173800  2**4
                  CONTENTS, ALLOC, LOAD, DATA
  3 .pdata        00004b18  00000001401cc000  00000001401cc000  00181400  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  4 .xdata        000000b4  00000001401d1000  00000001401d1000  00186000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  5 .zdebug_abbrev 00000266  00000001401d2000  00000001401d2000  00186200  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
  6 .zdebug_line  00046996  00000001401d3000  00000001401d3000  00186400  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
  7 .zdebug_frame 0001677c  00000001401fa000  00000001401fa000  001ad200  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
  8 .debug_gdb_scripts 00000030  0000000140202000  0000000140202000  001b4a00  2**0
                  CONTENTS, READONLY, DEBUGGING
  9 .zdebug_info  000a0e19  0000000140203000  0000000140203000  001b4c00  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
 10 .zdebug_loclists 0003b465  0000000140247000  0000000140247000  001f8a00  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
 11 .zdebug_rnglists 0001bc3d  0000000140262000  0000000140262000  00213600  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
 12 .zdebug_addr  00003b68  0000000140273000  0000000140273000  00223a00  2**0
                  CONTENTS, READONLY, DEBUGGING, COMPRESSED
 13 .idata        0000053e  0000000140274000  0000000140274000  00224a00  2**2
                  CONTENTS, ALLOC, LOAD, DATA
 14 .reloc        00003ac4  0000000140275000  0000000140275000  00225000  2**2
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
 15 .symtab       0001a554  0000000140279000  0000000140279000  00228c00  2**2
                  CONTENTS, READONLY
```

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

Ok giờ dump bytecode ra thôi

```
OFF=$((0x174be0))
COUNT=545
BS=4096

dd if=mini_vm.exe of=bytecode.bin bs=$BS skip=$((OFF/BS)) status=none
dd if=mini_vm.exe of=bytecode.bin bs=1 skip=$((OFF - (OFF/BS)*BS)) count=$COUNT seek=0 conv=notrunc status=none
```

### disassemble bytecode và nhận diện pattern check

Ta disasm theo rule sau:
- opcode cần immediate: 0x10, 0x30
- opcode 1 byte: 0x22, 0x31, 0xFE, 0xFF

Ta sẽ thấy nó lặp theo khuôn sau với mỗi kí tự `i`
```
30 i        ; push flag[i]
10 k        ; push key
22          ; xor
10 expected ; push expected
31          ; eq
FE          ; check (phải == 1)
```

=> điều kiện là
```
(flag[i] ^ k) == expected
=> flag[i] == k ^ expected
```

Code solve 
```python 
#!/usr/bin/env python3
import sys

def main():
    path = sys.argv[1] if len(sys.argv) > 1 else "bytecode.bin"
    bc = open(path, "rb").read()
    constraints = []
    for p in range(len(bc) - 8):
        if (bc[p]   == 0x30 and
            bc[p+2] == 0x10 and
            bc[p+4] == 0x22 and
            bc[p+5] == 0x10 and
            bc[p+7] == 0x31 and
            bc[p+8] == 0xFE):
            idx = bc[p+1]
            key = bc[p+3]
            exp = bc[p+6]
            constraints.append((idx, key, exp))

    if not constraints:
        print("No constraints found. Pattern not present or bytecode differs.")
        return

    max_idx = max(idx for idx, _, _ in constraints)
    flag = bytearray(max_idx + 1)

    for idx, key, exp in constraints:
        flag[idx] = key ^ exp
    print("len_constraints =", len(constraints))
    print("flag_bytes =", " ".join(f"{b:02x}" for b in flag))
    print(flag.decode(errors="replace"))

if __name__ == "__main__":
    main()
```

<details>
<summary><b>FLAG</b></summary>
    InfosecPTIT{y0u_H4ve_8Een_S0LVeD_My_cH4llEn9e_M1V1_vM_:3333}
</details>