Last active
May 29, 2020 19:49
-
-
Save singe/a21b7c2e39187a4aa4368204c6790147 to your computer and use it in GitHub Desktop.
Simple canary token binary wrapper
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "canary32.h" | |
// Modified from https://sourceforge.net/projects/cyoencode/ | |
static const char* const BASE32_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567="; | |
size_t cyoBase32EncodeA(char* dest, const void* src, size_t srcBytes) | |
{ | |
if (srcBytes > 153) | |
return 0; // Hostname max is 253, which means input can't be more than 153 I think | |
if (dest && src) | |
{ | |
unsigned char* pSrc = (unsigned char*)src; | |
char* pDest = dest; | |
size_t dwSrcSize = srcBytes; | |
size_t dwDestSize = 0; | |
size_t dwBlockSize; | |
unsigned char n[8]; | |
while (dwSrcSize >= 1) | |
{ | |
/* Encode inputs */ | |
dwBlockSize = (dwSrcSize < BASE32_INPUT ? dwSrcSize : BASE32_INPUT); | |
n[0] = n[1] = n[2] = n[3] = n[4] = n[5] = n[6] = n[7] = 0; | |
switch (dwBlockSize) | |
{ | |
case 5: | |
n[7] = (pSrc[4] & 0x1f); | |
n[6] = ((pSrc[4] & 0xe0) >> 5); | |
case 4: | |
n[6] |= ((pSrc[3] & 0x03) << 3); | |
n[5] = ((pSrc[3] & 0x7c) >> 2); | |
n[4] = ((pSrc[3] & 0x80) >> 7); | |
case 3: | |
n[4] |= ((pSrc[2] & 0x0f) << 1); | |
n[3] = ((pSrc[2] & 0xf0) >> 4); | |
case 2: | |
n[3] |= ((pSrc[1] & 0x01) << 4); | |
n[2] = ((pSrc[1] & 0x3e) >> 1); | |
n[1] = ((pSrc[1] & 0xc0) >> 6); | |
case 1: | |
n[1] |= ((pSrc[0] & 0x07) << 2); | |
n[0] = ((pSrc[0] & 0xf8) >> 3); | |
break; | |
default: | |
assert(0); | |
} | |
pSrc += dwBlockSize; | |
dwSrcSize -= dwBlockSize; | |
/* Validate */ | |
for (int i=0; i < 8; i++) | |
assert(n[i] <= 31); | |
/* Padding */ | |
switch (dwBlockSize) | |
{ | |
case 1: n[2] = n[3] = 32; | |
case 2: n[4] = 32; | |
case 3: n[5] = n[6] = 32; | |
case 4: n[7] = 32; | |
case 5: | |
break; | |
default: | |
assert(0); | |
} | |
/* 8 outputs */ | |
for (int i=0; i < 8; i++) { | |
if (n[i] == 32) break; | |
dwDestSize++; | |
if (dwDestSize % 64 == 0) { | |
*pDest++ = '.'; | |
dwDestSize++; | |
} | |
*pDest++ = BASE32_TABLE[n[i]]; | |
} | |
} | |
*pDest++ = '\x0'; /*append terminator*/ | |
//sranddev(); | |
//int i = snprintf(dest, MAX_HOSTNAME, "%s.G%02d", dest, rand()%99); | |
srand(time(NULL)); | |
char foo[MAX_HOSTNAME]; | |
int i = snprintf(foo, MAX_HOSTNAME, "%s.G%02d", dest, rand()%99); | |
i = snprintf(dest, MAX_HOSTNAME, "%s", foo); | |
if (i >= MAX_HOSTNAME) | |
return 0; //encoded value exceeds hostname max | |
else | |
return i; | |
} | |
else | |
return 0; /*ERROR - null pointer*/ | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <time.h> | |
#define MAX_HOSTNAME 254 | |
#define BASE32_INPUT 5 | |
size_t cyoBase32EncodeA(char* dest, const void* src, size_t srcBytes); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM alpine:latest as builder | |
LABEL maintainer="@singe at SensePost <[email protected]>" | |
RUN apk update && apk --no-cache add \ | |
build-base \ | |
&& rm -rf /var/cache/apk/* | |
WORKDIR / | |
COPY yellow.c canary32.c canary32.h / | |
RUN gcc -o yellow yellow.c canary32.c | |
From alpine:latest | |
LABEL maintainer="@singe at SensePost <[email protected]>" | |
COPY --from=builder /yellow /bin/ | |
RUN mv /usr/bin/id /usr/bin/id.canary \ | |
&& ln -s /bin/yellow /usr/bin/id |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
A simple library for triggering a canary token. | |
By @singe | |
Compile it as a shared library: | |
gcc -shared -fPIC libyellow.c canary32.c -o libyellow.so | |
Setup: | |
Register your own DNS canary token from Thinkst at https://canarytokens.org/ | |
and place it in TOKEN below. | |
Put the library somewhere you're comfortable with, and put it in | |
LD_PRELOAD. For example: | |
cp libyellow.so /usr/lib | |
echo /usr/lib/libyellow.so >> /etc/ld.so.preload | |
Usage: | |
If anyone executes one of your binaries, you'll get a Canary notification. | |
**/ | |
#include <netdb.h> | |
#include <stdlib.h> | |
#include <stdio.h> | |
#include "canary32.h" | |
#define TOKEN "XXXX.canarytokens.com" | |
#define FILENAMESIZE 500 | |
int yellow(int argc, char **argv, char **env) | |
{ | |
struct addrinfo *res; | |
char hostname[MAX_HOSTNAME], fqdn[FILENAMESIZE]; | |
int len = cyoBase32EncodeA(hostname, argv[0], strlen(argv[0])); | |
// Trigger our canary token | |
if (len == 0) | |
getaddrinfo(TOKEN,NULL,NULL,&res); | |
else { | |
snprintf(fqdn, FILENAMESIZE, "%s.%s", hostname, TOKEN); | |
getaddrinfo(fqdn,NULL,NULL,&res); | |
} | |
freeaddrinfo(res); | |
return 0; | |
} | |
__attribute__((section(".init_array"))) static void *foo_constructor = &yellow; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
A simple binary wrapper for triggering a canary token. | |
By @singe | |
Setup: | |
Register your own DNS canary token from Thinkst at https://canarytokens.org/ | |
and place it in TOKEN below. | |
Move the legit binary to use the extension you defined below, then either | |
copy this binary to that or use a symlink. For example: | |
cp yellow /usr/bin | |
cd /usr/bin | |
mv id id.canary | |
ln -s yellow id | |
Compiling: | |
gcc -o yellow yellow.c canary32.c | |
Usage: | |
If anyone executes one of your binaries, you'll get a Canary notification. | |
**/ | |
#include <stdio.h> | |
#include <netdb.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include "canary32.h" | |
#define TOKEN "XXXX.canarytokens.com" | |
// Use whatever extension you like | |
#define EXTENSION ".canary" | |
// 200 bytes should be enough for anyone - Not Bill Gates | |
#define FILENAMESIZE 500 | |
int main(int argc, char *argv[], char *environ[]) | |
{ | |
struct addrinfo *res; | |
char hostname[MAX_HOSTNAME], fqdn[FILENAMESIZE]; | |
int len = cyoBase32EncodeA(hostname, argv[0], strlen(argv[0])); | |
// Trigger our canary token | |
if (len == 0) | |
getaddrinfo(TOKEN,NULL,NULL,&res); | |
else { | |
snprintf(fqdn, FILENAMESIZE, "%s.%s", hostname, TOKEN); | |
getaddrinfo(fqdn,NULL,NULL,&res); | |
printf("%s",fqdn); | |
} | |
freeaddrinfo(res); | |
// Append our extension to the called filename to get the real one | |
char realexe[FILENAMESIZE]; | |
snprintf(realexe, FILENAMESIZE, "%s.%s", argv[0], EXTENSION); | |
// PATH lookup the exec and replace this process with it | |
// Preserving the passed args and environment | |
execvp(realexe, argv); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment