Skip to content

Latest commit

 

History

History
129 lines (114 loc) · 4.3 KB

EmojiVM_en.md

File metadata and controls

129 lines (114 loc) · 4.3 KB

HITCON CTF Quals - 2019

Reverse / 187 - EmojiVM

A simple VM that takes emojis as input! Try figure out the secret!

Author: bruce30262

77 Teams solved.

Solution

By @jaidTw

Reverse the binary and found that it read the source file then load it into std::wstring. It picks a wchar_t from the code at once to parse as an opcode.

Here's the type of all opcodes, we named it based on guessing its functionality.

  • NOP
  • ADD, SUB, MUL, MOD, XOR, AND, LT, EQ : op1 op op2
  • JMP : ip = op
  • JNZ, JZ : if(op1 cond 0) ip = op2
  • PUSH, POP
  • MVGPTRIO, WRGPTRIO : Read/Write a byte to GPTR[op1][op2]
  • ALLOC, FREE : Allocate/Release a type of space called "GPTR", at most 10 chunks, each size not exceeding 0x5DC.
  • RDSTRI, PRSTRI : Read/Write GPTR[op]
  • DMPSTK : Dump stack from top
  • PRINT : Print stack top as number
  • EXIT

This is a classical stack machine, operation will pop the stack to get operands, and push the result back after. All instructions are encoded as a single wchar_t except PUSH, which will additionally extract one more wchar_t behinds and push it onto the stack.

Then, we found there was a piece of code setting some kind of mapping during the initialization. After testing, we knew that it's the mapping of Emoji -> Opcode. There was another mapping below, which is for Emoji -> Number.

After understanding how it works, we can build the disassembler and assembler. Then we disassemble chal.evm and mark the byte offset of each instruction to get chal.d for reading.

6808  PUSH 1;
6810  RDSTRI;

The RDSTRI at 6810 is reading our input. So we can split the code here. The part before is for initialization and printing messages, and the part after will check our flag. We keep decompile it manually to get tmp2.d

After printing the message, it allocates 2 arrays.

GPTR[2] = [24, 5, 29, 16, 66, 9, 74, 36, 0, 91, 8, 23, 64, 0, 114, 48, 9, 108, 86, 64, 9, 91, 5, 26, 0]
GPTR[4] = [142, 99, 205, 18, 75, 88, 21, 23, 81, 34, 217, 4, 81, 44, 25, 21, 134, 44, 209, 76, 132, 46, 32, 6, 0]

There are some kinds of transformation after reading the input.

7407  i = 0;
      do {
7408    off = i % 4;
7425    if(off == 0)
          GPTR[3, i] = GPTR[1, i] + 30;
7474    else if(off == 1)
          GPTR[3, i] = 7 ^ (GPTR[1, i] - 8);
7527    else if(off == 2)
          GPTR[3, i] = ((GPTR[1, i] + 44) ^ 68) - 4;
7580    else if(off == 3)
          GPTR[3, i] = (GPTR[1, i] ^ 101) ^ (172 & 20)
7633    i += 1
7658  } while(i < 24)

the result will be compared to GPTR[4], and if they are equal, input XOR GPTR[2] will be printed out, which is the flag.

8075  i = 0
8084  off = 0
      do {
8093    if(GPTR[3, i] == GPTR[4, i]) {
8135      off += 1;
        } else {
8160      off -= 1;
        }
8179    i += 1;
8192  } while(i < 24)
8346  if(off != 24);
8385    GOTO @fail;
8407  i = 0;
      do {
8429    GPTR[2, i] = GPTR[1, i] ^ GPTR[2, i];
8437    i += 1;
8458  while(i < 24);
8534  GOTO @correct;

Thus, we can get the input by doing the inverse of transformation at 7407 on GPTR[4].

#include <stdio.h>
#include <stdlib.h>

int a[] = {24, 5, 29, 16, 66, 9, 74, 36, 0, 91, 8, 23, 64, 0, 114, 48, 9, 108, 86, 64, 9, 91, 5, 26, 0};
int b[] = {142, 99, 205, 18, 75, 88, 21, 23, 81, 34, 217, 4, 81, 44, 25, 21, 134, 44, 209, 76, 132, 46, 32, 6, 0};
int c[24];

int main(void) {
    for(int i = 0; i < 24; ++i) {
        if(i % 4 == 0) {
            c[i] = b[i] - 30;
        } else if(i % 4 == 1) {
            c[i] = (b[i] ^ 7) + 8;
        } else if(i % 4 == 2) {
            c[i] = ((b[i] + 4) ^ 68) - 44;
        } else if(i % 4 == 3) {
            c[i] = (b[i] ^ (172 & 20)) ^ 101;
        }
        putchar((c[i]) & 0xFF);
    }
}
$ gcc sol.c -o sol
$ ./sol
plis-g1v3-me33-th3e-f14g
$ ./sol | ./emojivm ./chalevm
*************************************
*                                   *
*             Welcome to            *
*        EmojiVM 😀😁🤣🤔🤨😮       *
*       The Reverse Challenge       *
*                                   *
*************************************

Please input the secret: 😍
hitcon{R3vers3_Da_3moj1}