mirror of
https://github.com/CPunch/Laika.git
synced 2024-11-22 04:50:06 +00:00
Tool: added VM Test
- includes a tiny demo for decoding secret messages
This commit is contained in:
parent
36c3c8a65f
commit
a4e04297a7
@ -4,7 +4,9 @@
|
|||||||
/* Laika VM:
|
/* Laika VM:
|
||||||
This is an obfuscation technique where vital code can be executed in a
|
This is an obfuscation technique where vital code can be executed in a
|
||||||
stack-based VM, inlined into the function. The VM instruction-set is fairly
|
stack-based VM, inlined into the function. The VM instruction-set is fairly
|
||||||
simple, see the OP_* for avaliable opcodes and their expected arguments.
|
simple, see the OP_* enum for avaliable opcodes and their expected arguments.
|
||||||
|
The VM is turing-complete, however the instruction-set has been curated to
|
||||||
|
fit this specific use case.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
@ -44,8 +46,9 @@ enum {
|
|||||||
OP_EXIT,
|
OP_EXIT,
|
||||||
OP_LOADCONST, /* stk_indx[uint8_t] = const_indx[uint8_t] */
|
OP_LOADCONST, /* stk_indx[uint8_t] = const_indx[uint8_t] */
|
||||||
OP_PUSHLIT, /* stk_indx[uint8_t].i = uint8_t */
|
OP_PUSHLIT, /* stk_indx[uint8_t].i = uint8_t */
|
||||||
OP_READ, /* stk_indx[uint8_t] = *(int8_t*)stk_indx[uint8_t] */
|
OP_READ, /* stk_indx[uint8_t].i = *(int8_t*)stk_indx[uint8_t] */
|
||||||
OP_WRITE, /* *(uint8_t*)stk_indx[uint8_t] = stk_indx[uint8_t] */
|
OP_WRITE, /* *(uint8_t*)stk_indx[uint8_t].ptr = stk_indx[uint8_t].i */
|
||||||
|
OP_INCPTR, /* stk_indx[uint8_t].ptr++ */
|
||||||
|
|
||||||
/* arithmetic */
|
/* arithmetic */
|
||||||
OP_ADD, /* stk_indx[uint8_t] = stk_indx[uint8_t] + stk_indx[uint8_t] */
|
OP_ADD, /* stk_indx[uint8_t] = stk_indx[uint8_t] + stk_indx[uint8_t] */
|
||||||
@ -102,6 +105,11 @@ LAIKA_FORCEINLINE void laikaV_execute(struct sLaikaV_vm *vm) {
|
|||||||
*(uint8_t*)vm->stack[ptr].ptr = vm->stack[indx].i;
|
*(uint8_t*)vm->stack[ptr].ptr = vm->stack[indx].i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case OP_INCPTR: {
|
||||||
|
uint8_t ptr = READBYTE;
|
||||||
|
vm->stack[ptr].ptr++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case OP_ADD: BINOP(+);
|
case OP_ADD: BINOP(+);
|
||||||
case OP_SUB: BINOP(-);
|
case OP_SUB: BINOP(-);
|
||||||
case OP_MUL: BINOP(*);
|
case OP_MUL: BINOP(*);
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.10)
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
add_subdirectory(genkey)
|
add_subdirectory(genkey)
|
||||||
|
add_subdirectory(vmtest)
|
||||||
|
14
tools/vmtest/CMakeLists.txt
Normal file
14
tools/vmtest/CMakeLists.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.10)
|
||||||
|
|
||||||
|
project(vmTest VERSION 1.0)
|
||||||
|
|
||||||
|
# Put CMake targets (ALL_BUILD/ZERO_CHECK) into a folder
|
||||||
|
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||||
|
|
||||||
|
# compile vmTest
|
||||||
|
file(GLOB_RECURSE VMTESTSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c)
|
||||||
|
add_executable(vmTest ${VMTESTSOURCE})
|
||||||
|
target_link_libraries(vmTest PUBLIC LaikaLib)
|
||||||
|
|
||||||
|
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
|
||||||
|
target_compile_definitions(vmTest PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
|
46
tools/vmtest/src/main.c
Normal file
46
tools/vmtest/src/main.c
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lvm.h"
|
||||||
|
#include "lbox.h"
|
||||||
|
|
||||||
|
/* VM BOX Demo:
|
||||||
|
A secret message has been xor'd, this tiny bytecode chunk decodes 'data' into
|
||||||
|
'unlockedData'. Obviously you wouldn't want a key this simple, more obfuscation
|
||||||
|
would be good (byte swapping, revolving xor key, etc.)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int main(int argv, char **argc) {
|
||||||
|
uint8_t data[] = {
|
||||||
|
0x96, 0xBB, 0xB2, 0xB2, 0xB1, 0xFE, 0x89, 0xB1,
|
||||||
|
0xAC, 0xB2, 0xBA, 0xFF, 0xDE, 0x20, 0xEA, 0xBA,
|
||||||
|
0xCE, 0xEA, 0xFC, 0x01, 0x9C, 0x23, 0x4D, 0xEE
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sLaikaB_box box = {
|
||||||
|
{0}, /* reserved */
|
||||||
|
{ /* stack layout:
|
||||||
|
[0] - unlockedData (ptr)
|
||||||
|
[1] - data (ptr)
|
||||||
|
[2] - key (uint8_t)
|
||||||
|
[3] - working data (uint8_t)
|
||||||
|
*/
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 0, 0),
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_LOADCONST, 1, 1),
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_PUSHLIT, 2, 0xDE),
|
||||||
|
/* LOOP_START */
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_READ, 3, 1), /* load data into working data */
|
||||||
|
LAIKA_MAKE_VM_IABC(OP_XOR, 3, 3, 2), /* xor data with key */
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_WRITE, 0, 3), /* write data to unlockedData */
|
||||||
|
LAIKA_MAKE_VM_IA(OP_INCPTR, 0),
|
||||||
|
LAIKA_MAKE_VM_IA(OP_INCPTR, 1),
|
||||||
|
LAIKA_MAKE_VM_IAB(OP_TESTJMP, 3, -17), /* exit loop on null terminator */
|
||||||
|
OP_EXIT
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
laikaB_unlock(&box, data);
|
||||||
|
printf("%s\n", box.unlockedData);
|
||||||
|
laikaB_lock(&box);
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user