Skip to content

Instantly share code, notes, and snippets.

@spacemeowx2
Last active May 28, 2018 12:02
Show Gist options
  • Save spacemeowx2/6e88851f7547854bef86f3a6e27e98cc to your computer and use it in GitHub Desktop.
Save spacemeowx2/6e88851f7547854bef86f3a6e27e98cc to your computer and use it in GitHub Desktop.
simple vm @ RCTF 2018
15 00 01 00 00 // X = 0x100
LABEL:
0E // X++
12 // A = [X]
0B // putchar(A)
0C 00 01 00 00 // loop
15 10 01 00 00
0E // X++
0A // getchar
0B
16 // [X] = A
0C 10 01 00 00
function nand(a, b){
return ~(a & b)
}
function xor(a, b) {
const z1 = nand(a, b)
const z2 = nand(z1, a)
const z3 = nand(z1, b)
return nand(z2, z3)
}
// 0x140: x
// 0x141: z1
// 0x142: z3
// 0x143: s[i]
// 0x144: xor(a, b)
// 0x145: LOOP_COUNT
03 40 01 00 00 // A = [0x140]
10 // X = A
11 F1 00 00 00 // A += 0xF1
13 // A = [A]
04 43 01 00 00 // [0x143] = A
08 // A = nand(A, X)
04 41 01 00 00 // [0x141] = A (z1)
10 // X = A
03 40 01 00 00 // A = [0x140] (x, b)
08 // A = nand(A, X)
04 42 01 00 00 // [0x142] = A (z3)
03 41 01 00 00 // A = [0x141] (z1)
03 43 01 00 00 // A = [0x143] (s[i], a)
08 // A = nand(A, X)
10 // X = A
03 42 01 00 00 // A = [0x142] (z3)
08 // A = nand(A, X)
04 44 01 00 00 // [0x144] = A (result)
// xor over
66 // 0B
03 40 01 00 00 // A = [0x140]
11 F1 00 00 00 // A += 0xF1
10 // X = A
03 44 01 00 00 // A = [0x144] (result)
16 // [X] = A
05 40 01 00 00 // X = [0x140]
0E // X++
06 40 01 00 00 // [0x140] = X
0C 45 01 00 00 55 00 00 00 // LOOP [0x145] (32 times)
FF
// 0x146: CMP Counter
03 46 01 00 00 // A = [0x146]
11 05 00 00 00 // A += 0x05
13 // A = [A]
10 // X = A
03 46 01 00 00 // A = [0x146]
11 11 01 00 00 // A += 0x111
13 // A = [A]
17 // A = A - X
18 60 01 00 00 // JNE
0C 46 01 00 00 B6 00 00 00 // LOOP [0x146] (32 times)
01 76 01 00 00// JMP 176
FF
15 50 01 00 00 // X = 0x150 wrong
// LOOP
0E // X++
12 // A = [X]
0B // putchar(A)
0C 50 01 00 00 65 01 00 00 // loop [0x150]
00 00 00 00 00 // exit
15 56 01 00 00 // X = 0x155 right
// LOOP
0E // X++
12 // A = [X]
0B // putchar(A)
0C 50 01 00 00 7B 01 00 00 // loop [0x150]
00 00 00 00 00 // exit
#include <stdio.h>
#include <stdlib.h>
#ifdef _DEBUG
#define DEBUG(...) printf(__VA_ARGS__)
#else
#define DEBUG(...)
#endif
enum OP {
OP_END,
OP_JMP,
OP_MOVi,
OP_LOAD,
OP_STORE,
OP_LOAD_X,
OP_STORE_X,
OP_ADD,
OP_NAND,
OP_OR,
OP_INPUT,
OP_OUTPUT,
OP_LOOP,
OP_INC,
OP_INC_X,
OP_X2A,
OP_A2X,
OP_ADDi,
OP_MOV_FROM_X,
OP_MOV_FROM_A,
OP_MOVi_A,
OP_MOVi_X,
OP_SET_X_A,
OP_SUB,
OP_JNE,
OP_NOP = 0x66,
OP_DEBUG = -1
};
struct VM {
int size;
void* data;
int A;
int X;
};
struct VM vm;
int run()
{
#define READ_INT() ({int _t; _t = *(int*)(p + i); i += sizeof(int); _t;})
char *p = (char *)vm.data;
int i = 0;
int src, dst, base, val;
while (233)
{
// DEBUG("POS: %x OP: %x AX: %x %x\n", i, p[i], vm.A, vm.X);
switch (p[i++])
{
case OP_END: // 0
return READ_INT();
break;
case OP_JMP: // 1
i = READ_INT();
break;
case OP_MOVi: // 2
dst = READ_INT();
val = READ_INT();
p[dst] = val;
break;
case OP_LOAD: // 3
src = READ_INT();
vm.A = p[src];
break;
case OP_STORE: // 4
dst = READ_INT();
p[dst] = vm.A;
break;
case OP_LOAD_X: // 5
src = READ_INT();
vm.X = p[src];
break;
case OP_STORE_X: // 6
dst = READ_INT();
p[dst] = vm.X;
break;
case OP_ADD: // 7
vm.A += vm.X;
break;
case OP_NAND: // 8
vm.A = ~(vm.A & vm.X);
break;
case OP_INPUT: // 0A
vm.A = getchar();
break;
case OP_OUTPUT: // 0B
// DEBUG("Output: %x\n", vm.A);
putchar(vm.A);
break;
case OP_LOOP: // 0C
src = READ_INT();
dst = READ_INT();
// DEBUG("LOOP %d to %d\n", p[src], dst);
if (p[src]) {
i = dst;
p[src]--;
}
break;
case OP_INC_X: // 0E
vm.X++;
break;
case OP_X2A: // 0F
vm.A = vm.X;
break;
case OP_A2X: // 10
vm.X = vm.A;
break;
case OP_ADDi: // 11
val = READ_INT();
vm.A += val;
break;
case OP_INC:
vm.A++;
break;
case OP_MOV_FROM_X: // 12
vm.A = p[vm.X];
break;
case OP_MOV_FROM_A: // 13
vm.A = p[vm.A];
break;
case OP_MOVi_A: // 14
vm.A = READ_INT();
break;
case OP_MOVi_X: // 15
vm.X = READ_INT();
break;
case OP_SET_X_A: // 16
p[vm.X] = vm.A;
break;
case OP_SUB: // 17
vm.A -= vm.X;
break;
case OP_JNE: // 18
dst = READ_INT();
if (vm.A != 0)
{
i = dst;
}
break;
case OP_NOP:
break;
#ifdef _DEBUG
case OP_DEBUG:
puts("DEBUG");
break;
#endif
}
if (i >= vm.size)
{
break;
}
}
return 0;
}
#ifdef _DEBUG
void fuck()
{
FILE* fp = fopen("fuck.bin", "wb");
fwrite(vm.data, 1, vm.size, fp);
fclose(fp);
}
#endif
int main()
{
FILE* file = fopen("p.bin", "rb");
if (file == NULL)
{
puts("err 0");
return -1;
}
fseek(file, 0, SEEK_END);
vm.size = ftell(file);
fseek(file, 0, SEEK_SET);
if (vm.size <= 0)
{
puts("err 1");
return -1;
}
DEBUG("Size: %d\n", vm.size);
vm.data = malloc(vm.size);
if (vm.data == NULL)
{
puts("err 3");
return -1;
}
if (fread(vm.data, 1, vm.size, file) != vm.size)
{
puts("err 4");
return -1;
}
fclose(file);
DEBUG("Run\n");
if (run() != 0)
{
puts("err 5");
return -1;
}
free(vm.data);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment