Initial commit

This commit is contained in:
Kevin Haubris
2022-04-26 12:55:27 -05:00
commit 3213f9e9ad
27 changed files with 2834 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
*.o
*.out
+133
View File
@@ -0,0 +1,133 @@
all: x86_64 x86 mac_x86_64 test2_dup test2 test whoami whoami32 tasklist tasklist32 cat cat32 uname uname32 id id32 uname uname32 walk walk32 grep grep32 find find32 chmod chmod32 env env32 pwd pwd32 ifconfig ifconfig32
SOURCES:=./src/beacon_compatibility.c ./src/ELFLoader.c
x86_64:
gcc -Wall -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoader.out
x86_64D:
gcc -g -DDEBUG -Wall -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoaderD.out
mac_x86_64:
x86_64-apple-darwin20-clang -Wall -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoader_mac.out
mac_x86_64D:
x86_64-apple-darwin20-clang -g -DDEBUG -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoaderD_mac.out
mac_aarch64:
aarch64-apple-darwin20-clang -Wall -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoader_mac_aarch64.out
mac_aarch64D:
aarch64-apple-darwin20-clang -g -DDEBUG -Wall -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoaderD_mac_aarch64.out
win64:
x86_64-w64-mingw32-gcc -I ./includes/ -DTESTING_MAIN $(SOURCES) -o ELFLoader_win64.exe
win64D:
x86_64-w64-mingw32-gcc -DDEBUG -I ./includes/ -DTESTING_MAIN $(SOURCES) -o ELFLoaderD_win64.exe
win32:
i686-w64-mingw32-gcc -I ./includes/ -DTESTING_MAIN $(SOURCES) -o ELFLoader_win32.exe
win32D:
i686-w64-mingw32-gcc -DDEBUG -I ./includes/ -DTESTING_MAIN $(SOURCES) -o ELFLoaderD_win32.exe
test2_dup:
gcc -c -fPIC -I ./includes/ testobjects/test2_duplicatetext.c -o testobjects/test2_duplicatetext.o
test2:
gcc -c -fPIC -I ./includes/ testobjects/test2.c -o testobjects/test2.o
test:
gcc -c -fPIC -I ./includes/ testobjects/test.c -o testobjects/test.o
x86:
gcc -m32 -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoader32.out
x86D:
gcc -m32 -DDEBUG -I ./includes/ -DTESTING_MAIN $(SOURCES) -ldl -o ELFLoader32.out
# Example of compiling object files for 32 bit x86 architecture.
test32:
gcc -m32 -c -fno-stack-protector -fno-pie ./testobjects/test.c -o ./testobjects/test32.o
whoami:
gcc -c -fPIC -I ./includes/ SA/src/whoami.c -o SA/src/whoami.o
whoami32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/whoami.c -o SA/src/whoami32.o
tasklist:
gcc -c -fPIC -I ./includes/ SA/src/tasklist.c -o SA/src/tasklist.o
tasklist32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/tasklist.c -o SA/src/tasklist32.o
cat:
gcc -c -fPIC -I ./includes/ SA/src/cat.c -o SA/src/cat.o
cat32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/cat.c -o SA/src/cat32.o
uname:
gcc -c -fPIC -I ./includes/ SA/src/uname.c -o SA/src/uname.o
uname32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/uname.c -o SA/src/uname32.o
id:
gcc -c -fPIC -I ./includes/ SA/src/id.c -o SA/src/id.o
id32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/id.c -o SA/src/id32.o
walk:
gcc -c -fPIC -I ./includes/ SA/src/walk.c -o SA/src/walk.o
walk32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/walk.c -o SA/src/walk32.o
env:
gcc -c -fPIC -I ./includes/ SA/src/env.c -o SA/src/env.o
env32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/env.c -o SA/src/env32.o
grep:
gcc -c -fPIC -I ./includes/ SA/src/grep.c -o SA/src/grep.o
grep32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/grep.c -o SA/src/grep32.o
find:
gcc -c -fPIC -I ./includes/ SA/src/find.c -o SA/src/find.o
find32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/find.c -o SA/src/find32.o
chmod:
gcc -c -fPIC -I ./includes/ SA/src/chmod.c -o SA/src/chmod.o
chmod32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/chmod.c -o SA/src/chmod32.o
pwd:
gcc -c -fPIC -I ./includes/ SA/src/pwd.c -o SA/src/pwd.o
pwd32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/pwd.c -o SA/src/pwd32.o
ifconfig:
gcc -c -fPIC -I ./includes/ SA/src/ifconfig.c -o SA/src/ifconfig.o
ifconfig32:
gcc -m32 -c -fno-stack-protector -fno-pie -I ./includes/ SA/src/ifconfig.c -o SA/src/ifconfig32.o
clean:
rm -f ELFLoader*.out
rm -f ELFLoader*.exe
rm -f ./SA/src/*.o
rm -f testobjects/*.o
rm -f ELFLoader_public
.PHONY: x86_64 x86_64D test2_dup test2 test clean
+55
View File
@@ -0,0 +1,55 @@
# ELFLoader
This is a ELF object in memory loader/runner. The goal is to create a single
elf loader that can be used to run follow on capabilities across all x86_64 and
x86 nix operating systems.
## How it works
The way this loader works is that it has all the code needed to build and load
an ELF object for the OS its been compiled for, anything that gets sent to it
that isn't an elf file, isn't for the right arch, or if it links to something
that can't be resolved it ends up exiting out without attempting to run.
## Resolving Symbols
A key difference between the COFFLoader and this is that it uses the standard
definitions from the OS's libc instead of having to redefine every function used.
## Project Layout
``` sh
.
├── includes
│   ├── beacon_api.h
│   ├── beacon_compatibility.h
│   ├── debug.h
│   ├── ELFLoader.h
│   └── minimal_elf.h
├── Makefile
├── README.md
├── SA
│   └── src
│   ├── cat.c
│   ├── chmod.c
│   ├── env.c
│   ├── find.c
│   ├── grep.c
│   ├── id.c
│   ├── ifconfig.c
│   ├── pwd.c
│   ├── tasklist.c
│   ├── uname.c
│   ├── walk.c
│   └── whoami.c
├── Scripts
│   └── beacon_generate.py
├── src
│   ├── beacon_compatibility.c
│   └── ELFLoader.c
└── testobjects
├── getuid.c
├── test2.c
├── test2_duplicatetext.c
└── test.c
6 directories, 26 files
```
+51
View File
@@ -0,0 +1,51 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include "beacon_api.h"
int run_cat(char* filestr){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
memset(readin, 0, 2049);
if (filestr == NULL){
return 1;
}
fin = fopen(filestr, "r");
if (fin == NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Failed to open file: %s\n", filestr);
return 1;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
BeaconPrintf(CALLBACK_OUTPUT, "%s", readin);
memset(readin, 0, 2049);
}
BeaconPrintf(CALLBACK_OUTPUT, "\n");
(void)fclose(fin);
return 0;
}
int go(char* indata, int inlen){
datap parser;
char* filepath = NULL;
BeaconDataParse(&parser, indata, inlen);
filepath = BeaconDataExtract(&parser, NULL);
(void)run_cat(filepath);
return 0;
}
#ifdef TEST_CAT
int main(int argc, char* argv[]){
return run_cat(argv[1]);
}
#endif
+92
View File
@@ -0,0 +1,92 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "beacon_api.h"
int run_chmod(char* permissionString, char* filepath){
int arg1len = 0;
mode_t permissions = 0;
int tempvalue = 0;
char temparg[2] = {0};
int startvalue = 0;
int counter = 0;
/* NOTE: Yes this is gross, but I don't know of a better way to convert
* inputted ascii text to octal numbers, so this is how I'm doing it.
* It's a table of permission values that we can iterate over and use
* sort of as a state table. */
int options[][6] = {{00, 01000, 02000, 00, 04000},
{00, 00100, 00200, 00, 00400},
{00, 00010, 00020, 00, 00040},
{00, 00001, 00002, 00, 00004}};
if (permissionString == NULL || filepath == NULL){
return 1;
}
arg1len = strlen(permissionString);
printf("Arg1Len: %d\n", arg1len);
/* If len is 4, start at 0 */
if (arg1len == 3){
startvalue = 1;
}
if (arg1len < 3 || arg1len > 4){
return 1;
}
for (counter = 0; counter <= arg1len; counter++){
temparg[0] = permissionString[counter];
tempvalue = atoi(temparg);
printf("Tempvalue:%d\n", tempvalue);
if (tempvalue & 1){
permissions |= options[counter+startvalue][1];
}
if (tempvalue & 2){
permissions |= options[counter+startvalue][2];
}
if (tempvalue & 4){
permissions |= options[counter+startvalue][4];
}
}
chmod(filepath, permissions);
return 0;
}
int go(char* indata, int inlen){
datap parser;
char* filepath = NULL;
char* permissions = NULL;
int checkcode = 0;
BeaconDataParse(&parser, indata, inlen);
permissions = BeaconDataExtract(&parser, NULL);
filepath = BeaconDataExtract(&parser, NULL);
checkcode = run_chmod(permissions, filepath);
if (checkcode == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Chmod Success\n");
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "Chmod Success\n");
}
return 0;
}
#ifdef TEST_CHMOD
int main(int argc, char* argv[]){
if (argc < 2){
printf("%s 777 ./path/to/file.txt\n", argv[0]);
return 0;
}
return run_chmod(argv[1], argv[2]);
}
#endif
+31
View File
@@ -0,0 +1,31 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <dlfcn.h>
#include "beacon_api.h"
int run_env(void){
int counter = 0;
char** environ = getEnviron();
if (environ == NULL){
return 1;
}
while (environ[counter] != NULL){
BeaconPrintf(CALLBACK_OUTPUT, "%s\n", environ[counter]);
counter++;
}
return 0;
}
int go(char* indata, int inlen){
(void)run_env();
return 0;
}
#ifdef TEST_ENV
int main(void){
return run_env();
}
#endif
+232
View File
@@ -0,0 +1,232 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "beacon_api.h"
int cat_action(char* filestr){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
memset(readin, 0, 2049);
if (filestr == NULL){
return 1;
}
fin = fopen(filestr, "r");
if (fin == NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Failed to open file: %s\n", filestr);
return 1;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
BeaconPrintf(CALLBACK_OUTPUT, "%s", readin);
memset(readin, 0, 2049);
}
BeaconPrintf(CALLBACK_OUTPUT, "\n");
(void)fclose(fin);
return 0;
}
int readlink_action(char* filepath){
char outdata[255] = {0};
ssize_t readsize = 0;
readsize = readlink(filepath, outdata, 255);
if (readsize == -1){
BeaconPrintf(CALLBACK_OUTPUT, "%s: Failure\n", filepath);
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s: %s\n", filepath, outdata);
}
return 0;
}
/* Search section of bytes to see if searchTerm is there */
char* memsearch(char* bytes, char* searchTerm, int size){
int compareval = 0;
int counter = 0;
char* retcode = NULL;
for (counter=0; counter < size; counter++){
compareval = memcmp(bytes+counter, searchTerm, strlen(searchTerm));
if (compareval == 0){
retcode = bytes+counter;
break;
}
}
return retcode;
}
/* Search contents of a file, by reading everything in a loop and
* then compare it to the searchTerm with memsearch */
int search_contents(char* filestr, char* searchTerm){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
char* results = 0;
int returncode = 0;
memset(readin, 0, 2049);
if (filestr == NULL){
return 0;
}
fin = fopen(filestr, "r");
if (fin == NULL){
//printf("Failed to open file: %s\n", filestr);
return 0;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
results = memsearch(readin, searchTerm, readsize);
if (results != NULL){
returncode = 1;
break;
}
memset(readin, 0, 2049);
}
(void)fclose(fin);
return returncode;
}
/* Type == 1 == Find
* Type == 2 == Grep
* findaction == 1 == cat
* findaction == 2 == readlink
* partOrWhole == 1 == part
* */
char* GrepAndFind(int type, int depth, int maxdepth, const char *sDir, char* searchTerm, char* filename, int findaction, int partOrWhole)
{
char* buffer = NULL;
char *p = NULL;
DIR *dir_ptr; // the directory
struct dirent *direntp; // each entry
struct stat statval;
int foundtext = 0;
char* results = NULL;
int throttleCount = 0;
if (maxdepth != -1 && depth > maxdepth){
return NULL;
}
if (type != 0 && searchTerm == NULL){
return NULL;
}
if((dir_ptr = opendir(sDir)) == NULL){
#ifdef DEBUG
fprintf(stderr, "ls: cannot open %s\n", sDir);
#endif
}
else
{
while((direntp=readdir(dir_ptr)) != NULL){
p = (char *)malloc(strlen(sDir) + strlen(direntp->d_name) + 2);
if (p == NULL){
break;
}
strcpy(p, sDir);
strcat(p, "/");
strcat(p, direntp->d_name);
__xstat(0, p, &statval);
throttleCount++;
if (throttleCount%10 == 0){
throttleCount = 0;
usleep(1000);
}
/* Skip the . or .. files */
if (strcmp(".", direntp->d_name) != 0 && strcmp("..", direntp->d_name)){
if ((statval.st_mode & S_IFMT) == S_IFDIR){
//printf("Its a folder\n");
GrepAndFind(type, depth+1, maxdepth, p, searchTerm, filename, findaction, partOrWhole);
}
if (type == 1){
results = NULL;
if (partOrWhole == 1){
results = strstr(direntp->d_name, searchTerm);
}
else{
if (0 == strcmp(direntp->d_name, searchTerm)){
results = (void*)-1;
}
}
if (results != NULL && findaction == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
else if (results != NULL && findaction == 2){
readlink_action(p);
}
else if (results != NULL && findaction == 1){
cat_action(p);
}
}
else if (type == 2){
if (filename == NULL){
foundtext = search_contents(p, searchTerm);
if (foundtext){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
else{
results = strstr(direntp->d_name, filename);
if (results){
foundtext = search_contents(p, searchTerm);
if (foundtext){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
}
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s\n", p);
}
}
free(p);
}
closedir(dir_ptr);
}
return buffer;
}
int go(char* indata, int inlen){
datap parser;
char* folderpath = NULL;
char* searchpath = NULL;
char* filepath = NULL;
int maxdepth = 0;
int findaction = 0;
int partOrWhole = 0;
BeaconDataParse(&parser, indata, inlen);
folderpath = BeaconDataExtract(&parser, NULL);
searchpath = BeaconDataExtract(&parser, NULL);
filepath = BeaconDataExtract(&parser, NULL);
maxdepth = BeaconDataInt(&parser);
findaction = BeaconDataInt(&parser);
partOrWhole = BeaconDataInt(&parser);
(void)GrepAndFind(1, 0, maxdepth, folderpath, searchpath, filepath, findaction, partOrWhole);
return 0;
}
#ifdef TEST_FIND
int main(int argc, char* argv[]){
GrepAndFind(1, 0, atoi(argv[1]), argv[4], argv[5], argv[6], atoi(argv[2]), atoi(argv[3]));
return 0;
}
#endif
+240
View File
@@ -0,0 +1,240 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "beacon_api.h"
int cat_action(char* filestr){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
memset(readin, 0, 2049);
if (filestr == NULL){
return 1;
}
fin = fopen(filestr, "r");
if (fin == NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Failed to open file: %s\n", filestr);
return 1;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
BeaconPrintf(CALLBACK_OUTPUT, "%s", readin);
memset(readin, 0, 2049);
}
BeaconPrintf(CALLBACK_OUTPUT, "\n");
(void)fclose(fin);
return 0;
}
int readlink_action(char* filepath){
char outdata[255] = {0};
ssize_t readsize = 0;
readsize = readlink(filepath, outdata, 255);
if (readsize == -1){
BeaconPrintf(CALLBACK_OUTPUT, "%s: Failure\n", filepath);
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s: %s\n", filepath, outdata);
}
return 0;
}
/* Search section of bytes to see if searchTerm is there */
char* memsearch(char* bytes, char* searchTerm, int size){
int compareval = 0;
int counter = 0;
char* retcode = NULL;
for (counter=0; counter < size; counter++){
compareval = memcmp(bytes+counter, searchTerm, strlen(searchTerm));
if (compareval == 0){
retcode = bytes+counter;
break;
}
}
return retcode;
}
/* Search contents of a file, by reading everything in a loop and
* then compare it to the searchTerm with memsearch */
int search_contents(char* filestr, char* searchTerm){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
char* results = 0;
int returncode = 0;
memset(readin, 0, 2049);
if (filestr == NULL){
return 0;
}
fin = fopen(filestr, "r");
if (fin == NULL){
//printf("Failed to open file: %s\n", filestr);
return 0;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
results = memsearch(readin, searchTerm, readsize);
if (results != NULL){
returncode = 1;
break;
}
memset(readin, 0, 2049);
}
(void)fclose(fin);
return returncode;
}
/* Type == 1 == Find
* Type == 2 == Grep
* findaction == 1 == cat
* findaction == 2 == readlink
* partOrWhole == 1 == part
* */
char* GrepAndFind(int type, int depth, int maxdepth, const char *sDir, char* searchTerm, char* filename, int findaction, int partOrWhole)
{
char* buffer = NULL;
char *p = NULL;
DIR *dir_ptr; // the directory
struct dirent *direntp; // each entry
struct stat statval;
int foundtext = 0;
char* results = NULL;
int throttleCount = 0;
if (maxdepth != -1 && depth > maxdepth){
return NULL;
}
if (type != 0 && searchTerm == NULL){
return NULL;
}
if((dir_ptr = opendir(sDir)) == NULL){
#ifdef DEBUG
fprintf(stderr, "ls: cannot open %s\n", sDir);
#endif
}
else
{
while((direntp=readdir(dir_ptr)) != NULL){
p = (char *)malloc(strlen(sDir) + strlen(direntp->d_name) + 2);
if (p == NULL){
break;
}
strcpy(p, sDir);
strcat(p, "/");
strcat(p, direntp->d_name);
__xstat(0, p, &statval);
throttleCount++;
if (throttleCount%10 == 0){
throttleCount = 0;
usleep(1000);
}
/* Skip the . or .. files */
if (strcmp(".", direntp->d_name) != 0 && strcmp("..", direntp->d_name)){
if ((statval.st_mode & S_IFMT) == S_IFDIR){
//printf("Its a folder\n");
GrepAndFind(type, depth+1, maxdepth, p, searchTerm, filename, findaction, partOrWhole);
}
if (type == 1){
results = NULL;
if (partOrWhole == 1){
results = strstr(direntp->d_name, searchTerm);
}
else{
if (0 == strcmp(direntp->d_name, searchTerm)){
results = (void*)-1;
}
}
if (results != NULL && findaction == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
else if (results != NULL && findaction == 2){
readlink_action(p);
}
else if (results != NULL && findaction == 1){
cat_action(p);
}
}
else if (type == 2){
if (filename == NULL){
foundtext = search_contents(p, searchTerm);
if (foundtext){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
else{
results = strstr(direntp->d_name, filename);
if (results){
foundtext = search_contents(p, searchTerm);
if (foundtext){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
}
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s\n", p);
}
}
free(p);
}
closedir(dir_ptr);
}
return buffer;
}
int go(char* indata, int inlen){
datap parser;
char* folderpath = NULL;
char* searchpath = NULL;
char* filepath = NULL;
int maxdepth = 0;
int findaction = 0;
int partOrWhole = 0;
BeaconDataParse(&parser, indata, inlen);
folderpath = BeaconDataExtract(&parser, NULL);
searchpath = BeaconDataExtract(&parser, NULL);
filepath = BeaconDataExtract(&parser, NULL);
maxdepth = BeaconDataInt(&parser);
findaction = BeaconDataInt(&parser);
partOrWhole = BeaconDataInt(&parser);
BeaconPrintf(CALLBACK_OUTPUT, "Folder: %s\n", folderpath);
BeaconPrintf(CALLBACK_OUTPUT, "Search: %s\n", searchpath);
BeaconPrintf(CALLBACK_OUTPUT, "Filename: %s\n", filepath);
if (filepath[0] == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Setting it to NULL\n");
filepath = NULL;
}
BeaconPrintf(CALLBACK_OUTPUT, "Depth: %d\n", maxdepth);
(void)GrepAndFind(2, 0, maxdepth, folderpath, searchpath, filepath, findaction, partOrWhole);
return 0;
}
#ifdef TEST_GREP
int main(int argc, char* argv[]){
GrepAndFind(2, 0, atoi(argv[1]), argv[4], argv[5], argv[6], atoi(argv[2]), atoi(argv[3]));
return 0;
}
#endif
+64
View File
@@ -0,0 +1,64 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <pwd.h>
#include <grp.h>
#include <sys/types.h>
#include "beacon_api.h"
int run_id(void){
uid_t uid = 0;
gid_t gid = 0;
gid_t gidList[25] = {0};
char* username = NULL;
char* groupname = NULL;
struct passwd *pwd;
struct group *groupval;
int checkval = 0;
int counter = 0;
uid = getuid();
pwd = getpwuid(uid);
if (pwd == NULL){
username = calloc(strlen("UNKNOWN")+1, 1);
if (username) {
memcpy(username, "UNKNOWN", strlen("UNKNOWN"));
}
}
else{
username = calloc(strlen(pwd->pw_name)+1, 1);
if (username) {
memcpy(username, pwd->pw_name, strlen(pwd->pw_name));
}
}
gid = getgid();
checkval = getgroups(25, gidList);
groupval = getgrgid(gid);
BeaconPrintf(CALLBACK_OUTPUT, "uid=%d(%s) gid=%d(%s), groups=%d(%s)", uid, username?username:"ERROR", gid, groupval?groupval->gr_name:"ERROR", gid, groupval?groupval->gr_name:"ERROR");
if (checkval >0){
for (counter=0; counter < checkval; counter++){
groupval = getgrgid(gidList[counter]);
BeaconPrintf(CALLBACK_OUTPUT, ",%d(%s)",gidList[counter], groupval?groupval->gr_name:"ERROR");
}
}
BeaconPrintf(CALLBACK_OUTPUT, "\n");
if (username){
free(username);
}
return 0;
}
int go(char* indata, int inlen){
(void)run_id();
return 0;
}
#ifdef TEST_ID
int main(void){
return run_id();
}
#endif
+99
View File
@@ -0,0 +1,99 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <ifaddrs.h>
#include <netinet/in.h>
#include <net/ethernet.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <sys/types.h>
#include <errno.h>
#include "beacon_api.h"
int run_ifconfig(void){
struct ifaddrs *ifap = NULL;
struct ifaddrs *ifa = NULL;
struct ifaddrs *ifa2 = NULL;
int checkcode = 0;
struct sockaddr_in *sin = NULL;
struct sockaddr_in *sin_netmask = NULL;
struct sockaddr_in *sin_broadcast = NULL;
struct sockaddr_in6 *sin6 = NULL;
char ip6buf[256*2 + 1];
checkcode = getifaddrs(&ifap);
if (checkcode != 0){
return 0;
}
/* Loop through the entries once, with just AF_PACKET/AF_LINK types
* print the name, then iterate over the rest of the entries ignoring
* the AF_LINK/AF_PACKET case, and print the addresses we want to handle
* and print the unknown types encountered for future reference. */
for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
switch(ifa->ifa_addr->sa_family){
#ifdef __APPLE__
case AF_LINK:
#else
case AF_PACKET:
#endif
BeaconPrintf(CALLBACK_OUTPUT, "%s:\n", ifa->ifa_name);
for (ifa2 = ifap; ifa2; ifa2 = ifa2->ifa_next) {
if (strcmp(ifa->ifa_name, ifa2->ifa_name) != 0){
continue;
}
switch(ifa2->ifa_addr->sa_family){
case AF_INET:
sin = (struct sockaddr_in*)ifa2->ifa_addr;
sin_netmask = (struct sockaddr_in*)ifa2->ifa_netmask;
sin_broadcast = (struct sockaddr_in*) ifa2->ifa_broadaddr;
BeaconPrintf(CALLBACK_OUTPUT, "\tIP Address: %s\n", inet_ntoa(sin->sin_addr));
BeaconPrintf(CALLBACK_OUTPUT, "\tNetmask: %s\n", inet_ntoa(sin_netmask->sin_addr));
BeaconPrintf(CALLBACK_OUTPUT, "\tBroadcast: %s\n", inet_ntoa(sin_broadcast->sin_addr));
break;
case AF_INET6:
sin6 = (struct sockaddr_in6*)ifa2->ifa_addr;
inet_ntop(AF_INET6, &sin6->sin6_addr, ip6buf, sizeof(ip6buf));
BeaconPrintf(CALLBACK_OUTPUT, "\tIPv6 Address: %s\n", ip6buf);
break;
#ifdef __APPLE__
case AF_LINK:
#else
case AF_PACKET:
#endif
break;
default:
BeaconPrintf(CALLBACK_OUTPUT, "Unsupported address family: %d\n", ifa->ifa_addr->sa_family);
break;
}
}
break;
default:
break;
}
}
if (ifap){
freeifaddrs(ifap);
}
return 0;
}
int go(char* indata, int inlen){
(void)run_ifconfig();
return 0;
}
#ifdef TEST_IFCONFIG
int main(void){
(void)run_ifconfig();
return 0;
}
#endif
+32
View File
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include "beacon_api.h"
int run_pwd(void){
int retcode = 0;
char workingdir[256] = {0};
char* workdir = NULL;
workdir = getcwd(workingdir, 255);
if (workdir == NULL){
BeaconPrintf(CALLBACK_OUTPUT, "ERROR\n");
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s\n", workingdir);
}
return 0;
}
int go(char* indata, int inlen){
(void)run_pwd();
return 0;
}
#ifdef TEST_PWD
int main(void){
return run_pwd();
}
#endif
+238
View File
@@ -0,0 +1,238 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
#ifndef DEBUG
#include "beacon_api.h"
#else
#define BeaconOutput(x, y, z) write(1, y, z)
#endif
char* getContents(unsigned char* filepath, uint32_t* outsize){
FILE *fin = NULL;
uint32_t fsize = 0;
uint32_t readsize = 0;
unsigned char* buffer = NULL;
unsigned char* tempbuffer = NULL;
fin = fopen((char*)filepath, "rb");
if (fin == NULL){
return NULL;
}
//fseek(fin, 0, SEEK_END);
//fsize = ftell(fin);
fseek(fin, 0, SEEK_SET);
fsize = 0x10000;
tempbuffer = calloc(fsize, 1);
if (tempbuffer == NULL){
return NULL;
}
memset(tempbuffer, 0, fsize);
readsize = fread(tempbuffer, 1, fsize, fin);
*outsize = readsize;
fclose(fin);
if (readsize == 0){
free(tempbuffer);
return NULL;
}
buffer = calloc(readsize, 1);
if (buffer == NULL){
return NULL;
}
memset(buffer, 0, readsize);
memcpy(buffer, tempbuffer, readsize-1);
free(tempbuffer);
return (char*)buffer;
}
int go(char* indata, int inlen){
char* results = NULL;
char* tempresults = NULL;
DIR* procdir = NULL;
struct dirent *proc_entry;
char* filepath = NULL;
char proc_path[320];
char* statusfile = NULL;
char* cmdline = NULL;
char* ptr = NULL;
char* linename = NULL;
char* linecontents = NULL;
char* uid = NULL;
char* ppid = NULL;
char* state = NULL;
char* fullline = NULL;
int resultslen = 0;
uint32_t filesize = 0;
int i = 0;
filepath = calloc(4096, 1);
linename = calloc(256, 1);
linecontents = calloc(2048, 1);
uid = calloc(50, 1);
ppid = calloc(50, 1);
state = calloc(10, 1);
if (!filepath || !linename || !linecontents || !uid || !ppid || !state){
goto cleanup;
}
procdir = opendir( "/proc/" );
while( NULL != (proc_entry = readdir(procdir))){
if (strspn(proc_entry->d_name, "0123456789" ) == strlen(proc_entry->d_name)){
memset(proc_path, 0, 320);
memset(filepath, 0, 4096);
memset(linecontents, 0, 2048);
sprintf(proc_path, "/proc/%s/exe", proc_entry->d_name);
readlink(proc_path, filepath, 4095);
memset(proc_path, 0, 256);
sprintf(proc_path, "/proc/%s/status", proc_entry->d_name);
statusfile = getContents((unsigned char*)proc_path, &filesize);
if (statusfile == NULL){
continue;
}
sprintf(proc_path, "/proc/%s/cmdline", proc_entry->d_name);
cmdline = getContents((unsigned char*)proc_path, &filesize);
if (cmdline != NULL){
for (i=0; i<filesize-1; i++){
if (cmdline[i] == 0){
cmdline[i] = ' ';
}
}
}
ptr = strtok(statusfile, "\n");
while (ptr){
sscanf(ptr, "%s\t%s", linename, linecontents);
if (strcmp(linename, "Uid:") == 0){
memcpy(uid, linecontents, 49);
}
else if (strcmp(linename, "PPid:") == 0){
memcpy(ppid, linecontents, 49);
}
else if (strcmp(linename, "State:") == 0){
memcpy(state, linecontents, 9);
}
else if (cmdline != NULL){
if (filepath[0] == 0 ||strlen(filepath) < strlen(cmdline)){
if (strlen(cmdline) < 4095){
memcpy(filepath, cmdline, strlen(cmdline));
}
else{
memcpy(filepath, cmdline, 4095);
}
}
}
else if (filepath[0] == 0 && strcmp(linename, "Name:") == 0){
memcpy(filepath, linecontents, strlen(linecontents));
}
ptr = strtok(NULL, "\n");
}
fullline = calloc(strlen(uid)+strlen(ppid)+strlen(state)+strlen(filepath)+strlen(proc_entry->d_name)+25, 1);
if (fullline == NULL){
if (statusfile){
free(statusfile);
statusfile = NULL;
}
if (cmdline){
free(cmdline);
cmdline = NULL;
}
break;
}
sprintf(fullline, "%s\t%s\t%s\t%s\t%s\n", uid, proc_entry->d_name, ppid, state, filepath);
tempresults = realloc(results, resultslen+strlen(fullline)+1);
if (tempresults == NULL){
if (fullline){
free(fullline);
fullline = NULL;
}
if (statusfile){
free(statusfile);
statusfile = NULL;
}
if (cmdline){
free(cmdline);
cmdline = NULL;
}
goto error;
}
results = tempresults;
memset(results+resultslen, 0, strlen(fullline)+1);
memcpy(results+resultslen, fullline, strlen(fullline));
resultslen += strlen(fullline);
if (cmdline){
free(cmdline);
cmdline = NULL;
}
if (statusfile){
free(statusfile);
statusfile = NULL;
}
if (fullline){
free(fullline);
fullline = NULL;
}
}
}
BeaconOutput(CALLBACK_OUTPUT, results, strlen(results));
if (results){
free(results);
results = NULL;
}
goto cleanup;
retlab:
return 0;
error:
cleanup:
if (procdir){
closedir(procdir);
procdir = NULL;
}
/* Free all temporary allocated buffers*/
if (filepath){
memset(filepath, 0, 4096);
free(filepath);
filepath = NULL;
}
if (linename){
memset(linename, 0, 256);
free(linename);
linename = NULL;
}
if (linecontents){
memset(linecontents, 0, 2048);
free(linecontents);
linecontents = NULL;
}
if (uid){
memset(uid, 0, 50);
free(uid);
uid = NULL;
}
if (ppid){
memset(ppid, 0, 50);
free(ppid);
ppid = NULL;
}
if (state){
memset(state, 0, 10);
free(state);
state = NULL;
}
goto retlab;
}
#ifdef DEBUG
int main(void){
(void)go(NULL, 0);
return 0;
}
#endif
+26
View File
@@ -0,0 +1,26 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <sys/utsname.h>
#include "beacon_api.h"
int run_uname(void){
struct utsname values;
int retcode = 0;
retcode = uname(&values);
BeaconPrintf(CALLBACK_OUTPUT, "%s %s %s %s %s\n", values.sysname, values.nodename, values.release, values.version, values.machine);
return 0;
}
int go(char* indata, int inlen){
(void)run_uname();
return 0;
}
#ifdef TEST_UNAME
int main(void){
return run_uname();
}
#endif
+145
View File
@@ -0,0 +1,145 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "beacon_api.h"
/* Basic memory search that returns the offset */
char* memsearch(char* bytes, char* searchTerm, int size){
int compareval = 0;
int counter = 0;
char* retcode = NULL;
for (counter=0; counter < size; counter++){
compareval = memcmp(bytes+counter, searchTerm, strlen(searchTerm));
if (compareval == 0){
retcode = bytes+counter;
break;
}
}
return retcode;
}
/* Read chunks, and then compare the memory to that it has a few problems
* mostly that it will miss anything that happens to be in the overlap
* between readin chunks */
int search_contents(char* filestr, char* searchTerm){
FILE* fin = NULL;
char readin[2049];
size_t readsize = 1;
char* results = 0;
int returncode = 0;
memset(readin, 0, 2049);
if (filestr == NULL){
return 0;
}
fin = fopen(filestr, "r");
if (fin == NULL){
//printf("Failed to open file: %s\n", filestr);
return 0;
}
while (readsize != 0){
readsize = fread(readin, 1, 2048, fin);
results = memsearch(readin, searchTerm, readsize);
if (results != NULL){
returncode = 1;
break;
}
memset(readin, 0, 2049);
}
(void)fclose(fin);
return returncode;
}
/* Type == 1 == Find
* Type == 2 == Grep
* */
char* GrepAndFind(int type, int depth, int maxdepth, const char *sDir, char* searchTerm)
{
char* buffer = NULL;
char *p = NULL;
DIR *dir_ptr; // the directory
struct dirent *direntp; // each entry
struct stat statval;
int foundtext = 0;
char* results = NULL;
if (maxdepth != -1 && depth > maxdepth){
return NULL;
}
if (type != 0 && searchTerm == NULL){
return NULL;
}
if((dir_ptr = opendir(sDir)) == NULL){
#ifdef DEBUG
fprintf(stderr, "ls: cannot open %s\n", sDir);
#endif
}
else
{
while((direntp=readdir(dir_ptr)) != NULL){
p = (char *)malloc(strlen(sDir) + strlen(direntp->d_name) + 2);
if (p == NULL){
break;
}
strcpy(p, sDir);
strcat(p, "/");
strcat(p, direntp->d_name);
__xstat(0, p, &statval);
/* Skip the . or .. files */
if (strcmp(".", direntp->d_name) != 0 && strcmp("..", direntp->d_name)){
if ((statval.st_mode & S_IFMT) == S_IFDIR){
//printf("Its a folder\n");
GrepAndFind(type, depth+1, maxdepth, p, searchTerm);
}
if (type == 1){
results = strstr(direntp->d_name, searchTerm);
if (results != NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
else if (type == 2){
foundtext = search_contents(p, searchTerm);
if (foundtext){
BeaconPrintf(CALLBACK_OUTPUT, "Found: %s\n", p);
}
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "%s\n", p);
}
}
free(p);
}
closedir(dir_ptr);
}
return buffer;
}
int go(char* indata, int inlen){
datap parser;
char* folderpath = NULL;
int maxdepth = 0;
BeaconDataParse(&parser, indata, inlen);
maxdepth = BeaconDataInt(&parser);
folderpath = BeaconDataExtract(&parser, NULL);
(void)GrepAndFind(0, 0, maxdepth, folderpath, NULL);
return 0;
}
#ifdef TEST_WALK
int main(int argc, char* argv[]){
GrepAndFind(0, 0, 2, argv[1], argv[2]);
return 0;
}
#endif
+39
View File
@@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include "beacon_api.h"
#define PATH_MAX 2048
int test3(void){
printf("This is the test3 function\n");
return 0;
}
int go(char* indata, int inlen){
char* pwdOutput = NULL;
char* testptr = NULL;
pwdOutput = calloc(PATH_MAX+1, 1);
BeaconPrintf(CALLBACK_OUTPUT, "UID: %d EUID: %d\n", getuid(), geteuid());
if (pwdOutput != NULL){
testptr = getcwd(pwdOutput, PATH_MAX);
if (testptr != NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Current Working Directory: %s\n", testptr);
}
}
if (getuid() == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Running as root!!!!\n");
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "Running as a standard user.\n");
}
if (pwdOutput){
free(pwdOutput);
}
return 0;
}
+96
View File
@@ -0,0 +1,96 @@
from struct import pack, calcsize
import binascii
import cmd
class BeaconPack:
def __init__(self):
self.buffer = b''
self.size = 0
def getbuffer(self):
return pack("<L", self.size) + self.buffer
def addshort(self, short):
self.buffer += pack("<h", short)
self.size += 2
def addint(self, dint):
self.buffer += pack("<i", dint)
self.size += 4
def addstr(self, s):
if isinstance(s, str):
s = s.encode("utf-8")
fmt = "<L{}s".format(len(s) + 1)
self.buffer += pack(fmt, len(s)+1, s)
self.size += calcsize(fmt)
def addWstr(self, s):
if isinstance(s, str):
s = s.encode("utf-16_le")
fmt = "<L{}s".format(len(s) + 2)
self.buffer += pack(fmt, len(s)+2, s)
self.size += calcsize(fmt)
class MainLoop(cmd.Cmd):
def __init__(self):
cmd.Cmd.__init__(self)
self.BeaconPack = BeaconPack()
self.intro = "Beacon Argument Generator"
self.prompt = "Beacon>"
def do_addWString(self, text):
'''addWString String here
Append the wide string to the text.
'''
self.BeaconPack.addWstr(text)
def do_addString(self, text):
'''addString string here
Append the utf-8 string here.
'''
self.BeaconPack.addstr(text)
def do_generate(self, text):
'''generate
Generate the buffer for the BOF arguments
'''
outbuffer = self.BeaconPack.getbuffer()
print(binascii.hexlify(outbuffer))
def do_addint(self, text):
'''addint integer
Add an int32_t to the buffer
'''
try:
converted = int(text)
self.BeaconPack.addint(converted)
except:
print("Failed to convert to int\n");
def do_addshort(self, text):
'''addshort integer
Add an uint16_t to the buffer
'''
try:
converted = int(text)
self.BeaconPack.addshort(converted)
except:
print("Failed to convert to short\n");
def do_reset(self, text):
'''reset
Reset the buffer here.
'''
self.BeaconPack.buffer = b''
self.BeaconPack.size = 0
def do_exit(self, text):
'''exit
Exit the console
'''
return True
if __name__ == "__main__":
cmdloop = MainLoop()
cmdloop.cmdloop()
+65
View File
@@ -0,0 +1,65 @@
#ifndef ELFLOADER_H_
#define ELFLOADER_H_
/*Defines to map Elf_Phdr to Elf32_Phdr and whatnot*/
#if UINTPTR_MAX == 0xffffffff
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_Shdr Elf32_Shdr
#define ELF_R_TYPE(i) ((i) & 0xff)
#define ELF_R_SYM(x) ((x) >> 8)
#define SHT_REL_TYPE SHT_REL
#define X86
#else
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rela
#define Elf_Shdr Elf64_Shdr
#define ELF_R_TYPE(i) ((i) & 0xffffffff)
#define ELF_R_SYM(x) ((x) >> 32)
#define SHT_REL_TYPE SHT_RELA
#endif
typedef struct ELFInfo {
Elf_Ehdr *Header;
Elf_Phdr *progHeader;
int progHeaderSize;
Elf_Shdr *sectHeader;
int sectHeaderSize;
unsigned char* execPtr;
Elf_Sym *symbolTable;
char* stringTable;
char* sectionStringTable;
unsigned char** sectionMappings;
int* sectionMappingProts;
unsigned char* tempOffsetTable;
int tempOffsetCounter;
} ELFInfo_t;
/* x86_64 */
#ifdef WIN32
#define PROT_READ PAGE_EXECUTE_READWRITE
#define PROT_WRITE PAGE_EXECUTE_READWRITE
#define PROT_EXEC PAGE_EXECUTE_READWRITE
#endif
#if defined(__amd64__) || defined(__x86_64__)
unsigned char* ThunkTrampoline = (unsigned char*)"\x48\xb8\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xEE\xff\xe0";
int ThunkTrampolineSize = 12;
#define THUNKOFFSET 2
#define COMPILEDMACHINEARCH EM_X86_64
#endif
/* x86 */
#if defined(__i386__)
unsigned char* ThunkTrampoline = (unsigned char*)"\x68\x00\x00\x00\x00\x58\xff\xe0";
int ThunkTrampolineSize = 8;
#define THUNKOFFSET 1
#define COMPILEDMACHINEARCH EM_386
#endif
int ELFRunner(char* functionName, unsigned char* elfObjectData, unsigned int size, unsigned char* argumentdata, int argumentSize);
#endif
+58
View File
@@ -0,0 +1,58 @@
/*
* Cobalt Strike 4.X BOF compatibility layer
* -----------------------------------------
* The whole point of these files are to allow beacon object files built for CS
* to run fine inside of other tools without recompiling.
*
* Built off of the beacon.h file provided to build for CS.
*/
#ifndef BEACON_API_H_
#define BEACON_API_H_
/* Structures as is in beacon.h */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;
void BeaconDataParse(datap * parser, char * buffer, int size);
int BeaconDataInt(datap * parser);
short BeaconDataShort(datap * parser);
int BeaconDataLength(datap * parser);
char * BeaconDataExtract(datap * parser, int * size);
void BeaconFormatAlloc(formatp * format, int maxsz);
void BeaconFormatReset(formatp * format);
void BeaconFormatFree(formatp * format);
void BeaconFormatAppend(formatp * format, char * text, int len);
void BeaconFormatPrintf(formatp * format, char * fmt, ...);
char * BeaconFormatToString(formatp * format, int * size);
void BeaconFormatInt(formatp * format, int value);
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_ERROR 0x0d
#define CALLBACK_OUTPUT_UTF8 0x20
void BeaconPrintf(int type, char * fmt, ...);
void BeaconOutput(int type, char * data, int len);
/* Token Functions */
int BeaconIsAdmin();
uint32_t swap_endianess(uint32_t indata);
char* BeaconGetOutputData(int *outsize);
char** getEnviron(void);
#endif
+66
View File
@@ -0,0 +1,66 @@
/*
* Cobalt Strike 4.X BOF compatibility layer
* -----------------------------------------
* The whole point of these files are to allow beacon object files built for CS
* to run fine inside of other tools without recompiling.
*
* Built off of the beacon.h file provided to build for CS.
*/
#ifndef BEACON_COMPATIBILITY_H_
#define BEACON_COMPATIBILITY_H_
typedef struct beacon_function{
char* functionName;
void* function;
} beacon_function_t;
extern beacon_function_t BeaconInternalMapping[17];
#define BEACONINTERNALMAPPINGCOUNT 16
void* internalFunctionLookup(char* symbolName);
/* Structures as is in beacon.h */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;
void BeaconDataParse(datap * parser, char * buffer, int size);
int BeaconDataInt(datap * parser);
short BeaconDataShort(datap * parser);
int BeaconDataLength(datap * parser);
char * BeaconDataExtract(datap * parser, int * size);
void BeaconFormatAlloc(formatp * format, int maxsz);
void BeaconFormatReset(formatp * format);
void BeaconFormatFree(formatp * format);
void BeaconFormatAppend(formatp * format, char * text, int len);
void BeaconFormatPrintf(formatp * format, char * fmt, ...);
char * BeaconFormatToString(formatp * format, int * size);
void BeaconFormatInt(formatp * format, int value);
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_ERROR 0x0d
#define CALLBACK_OUTPUT_UTF8 0x20
void BeaconPrintf(int type, char * fmt, ...);
void BeaconOutput(int type, char * data, int len);
/* Token Functions */
int BeaconIsAdmin();
uint32_t swap_endianess(uint32_t indata);
char* BeaconGetOutputData(int *outsize);
char** getEnviron(void);
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef _DEBUG_H_
#define _DEBUG_H_
#if defined( DEBUG )
#define DEBUG_PRINT(x, ...) printf(x, ##__VA_ARGS__)
#else
#define DEBUG_PRINT(x, ...)
#endif
#endif
+205
View File
@@ -0,0 +1,205 @@
#ifndef MINIMAL_ELF_H_
#define MINIMAL_ELF_H_
/* Minimal elf definitions stripped from FreeBSD's headers
* and included so that there's no external dependencies
* for the mac version of the Loader.
* */
/*-
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
*
* Copyright (c) 1996-1998 John D. Polstra.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#define EI_NIDENT 16
#define EM_386 3
#define EM_X86_64 62
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_REL 9
#define R_386_32 1
#define R_386_PC32 2
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
typedef uint64_t Elf32_Lword;
typedef Elf32_Word Elf32_Hashelt;
typedef Elf32_Word Elf32_Size;
typedef Elf32_Sword Elf32_Ssize;
typedef uint64_t Elf64_Addr;
typedef uint16_t Elf64_Half;
typedef uint64_t Elf64_Off;
typedef int32_t Elf64_Sword;
typedef int64_t Elf64_Sxword;
typedef uint32_t Elf64_Word;
typedef uint64_t Elf64_Lword;
typedef uint64_t Elf64_Xword;
typedef Elf64_Word Elf64_Hashelt;
/* Non-standard class-dependent datatype used for abstraction. */
typedef Elf64_Xword Elf64_Size;
typedef Elf64_Sxword Elf64_Ssize;
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf64_Half e_type; /* File type. */
Elf64_Half e_machine; /* Machine architecture. */
Elf64_Word e_version; /* ELF format version. */
Elf64_Addr e_entry; /* Entry point. */
Elf64_Off e_phoff; /* Program header file offset. */
Elf64_Off e_shoff; /* Section header file offset. */
Elf64_Word e_flags; /* Architecture-specific flags. */
Elf64_Half e_ehsize; /* Size of ELF header in bytes. */
Elf64_Half e_phentsize; /* Size of program header entry. */
Elf64_Half e_phnum; /* Number of program header entries. */
Elf64_Half e_shentsize; /* Size of section header entry. */
Elf64_Half e_shnum; /* Number of section header entries. */
Elf64_Half e_shstrndx; /* Section name strings section. */
} Elf64_Ehdr;
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* File identification. */
Elf32_Half e_type; /* File type. */
Elf32_Half e_machine; /* Machine architecture. */
Elf32_Word e_version; /* ELF format version. */
Elf32_Addr e_entry; /* Entry point. */
Elf32_Off e_phoff; /* Program header file offset. */
Elf32_Off e_shoff; /* Section header file offset. */
Elf32_Word e_flags; /* Architecture-specific flags. */
Elf32_Half e_ehsize; /* Size of ELF header in bytes. */
Elf32_Half e_phentsize; /* Size of program header entry. */
Elf32_Half e_phnum; /* Number of program header entries. */
Elf32_Half e_shentsize; /* Size of section header entry. */
Elf32_Half e_shnum; /* Number of section header entries. */
Elf32_Half e_shstrndx; /* Section name strings section. */
} Elf32_Ehdr;
typedef struct {
Elf32_Word sh_name; /* Section name (index into the
section header string table). */
Elf32_Word sh_type; /* Section type. */
Elf32_Word sh_flags; /* Section flags. */
Elf32_Addr sh_addr; /* Address in memory image. */
Elf32_Off sh_offset; /* Offset in file. */
Elf32_Word sh_size; /* Size in bytes. */
Elf32_Word sh_link; /* Index of a related section. */
Elf32_Word sh_info; /* Depends on section type. */
Elf32_Word sh_addralign; /* Alignment in bytes. */
Elf32_Word sh_entsize; /* Size of each entry in section. */
} Elf32_Shdr;
typedef struct {
Elf64_Word sh_name; /* Section name (index into the
section header string table). */
Elf64_Word sh_type; /* Section type. */
Elf64_Xword sh_flags; /* Section flags. */
Elf64_Addr sh_addr; /* Address in memory image. */
Elf64_Off sh_offset; /* Offset in file. */
Elf64_Xword sh_size; /* Size in bytes. */
Elf64_Word sh_link; /* Index of a related section. */
Elf64_Word sh_info; /* Depends on section type. */
Elf64_Xword sh_addralign; /* Alignment in bytes. */
Elf64_Xword sh_entsize; /* Size of each entry in section. */
} Elf64_Shdr;
typedef struct {
Elf64_Word p_type; /* Entry type. */
Elf64_Word p_flags; /* Access permission flags. */
Elf64_Off p_offset; /* File offset of contents. */
Elf64_Addr p_vaddr; /* Virtual address in memory image. */
Elf64_Addr p_paddr; /* Physical address (not used). */
Elf64_Xword p_filesz; /* Size of contents in file. */
Elf64_Xword p_memsz; /* Size of contents in memory. */
Elf64_Xword p_align; /* Alignment in memory and file. */
} Elf64_Phdr;
typedef struct {
Elf32_Word p_type; /* Entry type. */
Elf32_Off p_offset; /* File offset of contents. */
Elf32_Addr p_vaddr; /* Virtual address in memory image. */
Elf32_Addr p_paddr; /* Physical address (not used). */
Elf32_Word p_filesz; /* Size of contents in file. */
Elf32_Word p_memsz; /* Size of contents in memory. */
Elf32_Word p_flags; /* Access permission flags. */
Elf32_Word p_align; /* Alignment in memory and file. */
} Elf32_Phdr;
/* Relocations that don't need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
} Elf32_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf32_Addr r_offset; /* Location to be relocated. */
Elf32_Word r_info; /* Relocation type and symbol index. */
Elf32_Sword r_addend; /* Addend. */
} Elf32_Rela;
typedef struct {
Elf32_Word st_name; /* String table index of name. */
Elf32_Addr st_value; /* Symbol value. */
Elf32_Word st_size; /* Size of associated object. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf32_Half st_shndx; /* Section index of symbol. */
} Elf32_Sym;
typedef struct {
Elf64_Word st_name; /* String table index of name. */
unsigned char st_info; /* Type and binding information. */
unsigned char st_other; /* Reserved (not used). */
Elf64_Half st_shndx; /* Section index of symbol. */
Elf64_Addr st_value; /* Symbol value. */
Elf64_Xword st_size; /* Size of associated object. */
} Elf64_Sym;
/* Relocations that don't need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
} Elf64_Rel;
/* Relocations that need an addend field. */
typedef struct {
Elf64_Addr r_offset; /* Location to be relocated. */
Elf64_Xword r_info; /* Relocation type and symbol index. */
Elf64_Sxword r_addend; /* Addend. */
} Elf64_Rela;
#endif
+431
View File
@@ -0,0 +1,431 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#ifndef WIN32
#include <sys/mman.h>
#include <dlfcn.h>
#else
#include <windows.h>
#endif
#include "debug.h"
#include "minimal_elf.h"
#include "ELFLoader.h"
#include "beacon_compatibility.h"
unsigned char* unhexlify(unsigned char* value, int *outlen){
unsigned char* retval = NULL;
char byteval[3] = {0};
int counter = 0;
int counter2 = 0;
char character = 0;
if (value == NULL){
return NULL;
}
DEBUG_PRINT("Unhexlify Strlen: %lu\n", (long unsigned int)strlen((char*)value));
if (value == NULL || strlen((char*)value)%2 != 0){
DEBUG_PRINT("Either value is NULL, or the hexlified string isn't valid\n");
goto errcase;
}
retval = calloc(strlen((char*)value)+1, 1);
if (retval == NULL){
goto errcase;
}
counter2 = 0;
for (counter = 0; counter < strlen((char*)value); counter += 2){
memcpy(byteval, value+counter, 2);
character = strtol(byteval, NULL, 16);
memcpy(retval+counter2, &character, 1);
counter2++;
}
*outlen = counter2;
errcase:
return retval;
}
int ELFRunner(char* functionName, unsigned char* elfObjectData, unsigned int size, unsigned char* argumentdata, int argumentSize){
#if defined(__amd64__) || defined(__x86_64__) || defined(__i386__) || (defined(DEBUG) && defined(ELFRUNNERTEST))
ELFInfo_t elfinfo;
int counter = 0;
int c2 = 0;
int (*ptr)(unsigned char*, int);
int retcode = 0;
memset(&elfinfo, 0, sizeof(ELFInfo_t));
elfinfo.Header = (Elf_Ehdr*) elfObjectData;
/* Verify that the data is an ELF file. */
if (elfObjectData[0] != '\x7f' || elfObjectData[1] != 'E' || elfObjectData[2] != 'L' || elfObjectData[3] != 'F'){
DEBUG_PRINT("Not an elf file\n");
retcode = 1;
goto errorcase;
}
/* Verify that the ELF file is a relocatable file, and not a shared object or binary */
if (elfinfo.Header->e_type != 1){
DEBUG_PRINT("ELF Type isn't relocatable type, bailing...\n");
retcode = 2;
goto errorcase;
}
if (elfinfo.Header->e_machine != COMPILEDMACHINEARCH){
DEBUG_PRINT("ERROR, not the machine type your running on\n");
retcode = -1;
goto errorcase;
}
DEBUG_PRINT("ELF Object Data: %p\n", elfObjectData);
DEBUG_PRINT("ELF Type: %d\n", elfinfo.Header->e_type);
DEBUG_PRINT("ELF Machine: %d\n", elfinfo.Header->e_machine);
DEBUG_PRINT("ELF Version: %d\n", elfinfo.Header->e_version);
DEBUG_PRINT("ELF Entry: 0x%lx\n", elfinfo.Header->e_entry);
DEBUG_PRINT("ELF ProgramHeaderOffset: 0x%lx\n", elfinfo.Header->e_phoff);
DEBUG_PRINT("ELF SectionHeaderOffset: 0x%lx\n", elfinfo.Header->e_shoff);
DEBUG_PRINT("ELF Flags: 0x%x\n", elfinfo.Header->e_flags);
DEBUG_PRINT("ELF Header Size: %d\n", elfinfo.Header->e_ehsize);
DEBUG_PRINT("ELF Program Header Entry Size: %d\n", elfinfo.Header->e_phentsize);
DEBUG_PRINT("ELF Program Header Entry Count: %d\n", elfinfo.Header->e_phnum);
DEBUG_PRINT("ELF Section Header Entry Size: %d\n", elfinfo.Header->e_shentsize);
DEBUG_PRINT("ELF Section Header Entry Count: %d\n", elfinfo.Header->e_shnum);
DEBUG_PRINT("ELF Section Header Table Index Entry: %d\n", elfinfo.Header->e_shstrndx);
/* Set all the headers and sizes */
elfinfo.progHeader = (Elf_Phdr*)(elfObjectData + elfinfo.Header->e_phoff);
elfinfo.sectHeader = (Elf_Shdr*)(elfObjectData + elfinfo.Header->e_shoff);
elfinfo.progHeaderSize = elfinfo.Header->e_phnum;
elfinfo.sectHeaderSize = elfinfo.Header->e_shnum;
/* This is usually whats important for standard in memory loaders, but since this is loading
* object files, this isn't actually used. Leaving in the loader so I can extend later on.*/
DEBUG_PRINT("Working with program headers, Count: %d\n", elfinfo.progHeaderSize);
for (counter = 0; counter < elfinfo.progHeaderSize; counter++){
DEBUG_PRINT("Program Header Entry Counter: %d\n", counter);
DEBUG_PRINT("\tOffset: 0x%lx\n", elfinfo.progHeader[counter].p_offset);
}
/* End the program header loop */
elfinfo.sectionMappings = calloc(elfinfo.sectHeaderSize*sizeof(char*), 1);
elfinfo.sectionMappingProts = calloc(elfinfo.sectHeaderSize*sizeof(int), 1);
/* Make sure that the section mappings and protections array is allocated, if not then error out. */
if (elfinfo.sectionMappings == NULL || elfinfo.sectionMappingProts == NULL){
DEBUG_PRINT("Failed to setup sectionMappings\n");
retcode = 3;
goto errorcase;
}
#ifdef WIN32
elfinfo.tempOffsetTable = VirtualAlloc(NULL, 255*ThunkTrampolineSize, MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
#else
elfinfo.tempOffsetTable = mmap(NULL, 255*ThunkTrampolineSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
elfinfo.tempOffsetCounter = 0;
if (elfinfo.tempOffsetTable == NULL){
DEBUG_PRINT("Failed to allocate the hacky GOT/Thunk function table.\n");
retcode = 4;
goto errorcase;
}
DEBUG_PRINT("Working over section headers, Count: %d\n", elfinfo.sectHeaderSize);
for (counter = 0; counter < elfinfo.sectHeaderSize; counter++){
int sectionProts = PROT_READ | PROT_WRITE;
DEBUG_PRINT("Section Header Entry Counter: %d\n", counter);
DEBUG_PRINT("\tName is %d\n", elfinfo.sectHeader[counter].sh_name);
DEBUG_PRINT("\tType is 0x%x\n", elfinfo.sectHeader[counter].sh_type);
DEBUG_PRINT("\tFlags are 0x%lx\n", elfinfo.sectHeader[counter].sh_flags);
/* Identify the memory permissions here */
if (elfinfo.sectHeader[counter].sh_flags & 0x1){
DEBUG_PRINT("\t\tWriteable Section\n");
sectionProts = PROT_READ | PROT_WRITE;
}
if (elfinfo.sectHeader[counter].sh_flags & 0x4){
DEBUG_PRINT("\t\tExecutable Section\n");
sectionProts = PROT_READ | PROT_EXEC;
}
if (elfinfo.sectHeader[counter].sh_size > 0 && elfinfo.sectHeader[counter].sh_type == SHT_PROGBITS){
#ifdef WIN32
elfinfo.sectionMappings[counter] = VirtualAlloc(NULL, elfinfo.sectHeader[counter].sh_size, MEM_COMMIT|MEM_RESERVE|MEM_TOP_DOWN, PAGE_EXECUTE_READWRITE);
#else
elfinfo.sectionMappings[counter] = mmap(NULL, elfinfo.sectHeader[counter].sh_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
#endif
if (elfinfo.sectionMappings[counter] == NULL){
DEBUG_PRINT("\t\t\tFailed to allocate memory for section\n");
retcode = 5;
goto errorcase;
}
memcpy(elfinfo.sectionMappings[counter], elfObjectData+elfinfo.sectHeader[counter].sh_offset, elfinfo.sectHeader[counter].sh_size);
}
else{
/* Not allocating memory because the section isn't needed for the program to run, just used to link. */
DEBUG_PRINT("\t\t\tNot allocating memory for section\n");
elfinfo.sectionMappings[counter] = NULL;
}
elfinfo.sectionMappingProts[counter] = sectionProts;
DEBUG_PRINT("\tAddr is 0x%lx\n", elfinfo.sectHeader[counter].sh_addr);
DEBUG_PRINT("\tOffset is 0x%lx\n", elfinfo.sectHeader[counter].sh_offset);
DEBUG_PRINT("\tSize is %ld\n", elfinfo.sectHeader[counter].sh_size);
DEBUG_PRINT("\tLink is %d\n", elfinfo.sectHeader[counter].sh_link);
DEBUG_PRINT("\tInfo is %d\n", elfinfo.sectHeader[counter].sh_info);
DEBUG_PRINT("\tAddrAlign is %ld\n", elfinfo.sectHeader[counter].sh_addralign);
DEBUG_PRINT("\tEntSize is %ld\n", elfinfo.sectHeader[counter].sh_entsize);
/* Locate the sections that we want to keep track to */
switch (elfinfo.sectHeader[counter].sh_type){
case SHT_SYMTAB:
DEBUG_PRINT("\t\tSymbol Table\n");
elfinfo.symbolTable = (Elf_Sym*)(elfObjectData + elfinfo.sectHeader[counter].sh_offset);
elfinfo.stringTable = (char*)(elfObjectData + elfinfo.sectHeader[elfinfo.sectHeader[counter].sh_link].sh_offset);
DEBUG_PRINT("\t\tSymbolTable: %p\n", elfinfo.symbolTable);
DEBUG_PRINT("\t\tStringTable: %p\n", elfinfo.stringTable);
break;
case SHT_STRTAB:
DEBUG_PRINT("\t\tString Table\n");
elfinfo.sectionStringTable = (char*)(elfObjectData + elfinfo.sectHeader[counter].sh_offset);
break;
default:
DEBUG_PRINT("\t\tCase Not Handled\n");
break;
}
}
DEBUG_PRINT("\nWorking over section headers, Round 2, Count: %d\n", elfinfo.sectHeaderSize);
for (counter = 0; counter < elfinfo.sectHeaderSize; counter++){
DEBUG_PRINT("Section Header Entry Counter: %d\n", counter);
#ifdef DEBUG
char* sym = elfinfo.sectionStringTable + elfinfo.sectHeader[counter].sh_name;
DEBUG_PRINT("\tName is %s\n", sym);
#endif
Elf_Rel* rel = (Elf_Rel*)(elfObjectData + elfinfo.sectHeader[counter].sh_offset);
DEBUG_PRINT("\tType is 0x%x\n", elfinfo.sectHeader[counter].sh_type);
DEBUG_PRINT("\tFlags are 0x%lx\n", elfinfo.sectHeader[counter].sh_flags);
DEBUG_PRINT("\tAddr is 0x%lx\n", elfinfo.sectHeader[counter].sh_addr);
DEBUG_PRINT("\tOffset is 0x%lx\n", elfinfo.sectHeader[counter].sh_offset);
DEBUG_PRINT("\tSize is %ld\n", elfinfo.sectHeader[counter].sh_size);
DEBUG_PRINT("\tLink is %d\n", elfinfo.sectHeader[counter].sh_link);
DEBUG_PRINT("\tInfo is %d\n", elfinfo.sectHeader[counter].sh_info);
DEBUG_PRINT("\tAddrAlign is %ld\n", elfinfo.sectHeader[counter].sh_addralign);
DEBUG_PRINT("\tEntSize is %ld\n", elfinfo.sectHeader[counter].sh_entsize);
/* Handle the relocations here */
if (elfinfo.sectHeader[counter].sh_type == SHT_REL_TYPE){
DEBUG_PRINT("\tRelocation Entries:\n");
for (c2 = 0; c2 < elfinfo.sectHeader[counter].sh_size / sizeof(Elf_Rel); c2++){
char* relocStr = elfinfo.stringTable + elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_name;
char WorkingTrampoline[ThunkTrampolineSize];
memcpy(WorkingTrampoline, ThunkTrampoline, ThunkTrampolineSize);
DEBUG_PRINT("\t\tSymbol: %s\n", relocStr);
DEBUG_PRINT("\t\tType: 0x%lx\n", ELF_R_TYPE(rel[c2].r_info));
DEBUG_PRINT("\t\tSymbolValue: 0x%lx\n", elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_value);
/* This is the section number where the relocation lives in at x + offset, if its 0 then its a symbol to get
* so get the address, store the address, increase the symbol count, and then continue */
DEBUG_PRINT("\t\tShndx: 0x%x\n", elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx);
if (elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx == 0){
/* This function is a function not defined in the object file, so if we can't resolve it then bail. */
void* symaddress = NULL;
int32_t relativeOffsetFunc = 0;
symaddress = internalFunctionLookup(relocStr);
/* TODO: Add an in process function lookup here too */
if (symaddress == NULL){
DEBUG_PRINT("Failed to find a function!!!!!\n");
retcode = 6;
goto errorcase;
}
DEBUG_PRINT("\t\tFound Function Address: %p\n", symaddress);
/* Copy over the symaddress to the location of the trampoline */
memcpy(WorkingTrampoline+THUNKOFFSET, &symaddress, sizeof(void*));
/* Copy the trampoline bytes over to the tempOffsetTable so relocations work */
DEBUG_PRINT("TempOffsetCounter: %d\n", elfinfo.tempOffsetCounter);
memcpy(elfinfo.tempOffsetTable+(elfinfo.tempOffsetCounter*ThunkTrampolineSize), WorkingTrampoline, ThunkTrampolineSize);
/* Calculate the relative offset of the function trampoline */
/* The logic to handle x86_64 is different then x86, so ifdef'ing these out for now */
#if defined(__amd64__) || defined(__x86_64__)
relativeOffsetFunc = (elfinfo.tempOffsetTable + (elfinfo.tempOffsetCounter *ThunkTrampolineSize))-(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset)+rel[c2].r_addend;
DEBUG_PRINT("\t\tRelativeOffsetFunc: 0x%x\n", relativeOffsetFunc);
/* Copy over the relative offset to the trampoline table */
memcpy(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, &relativeOffsetFunc, 4);
#elif defined(__i386__)
/* Need to correct this for x86 and 32 bit arm targets, think its good now. */
memcpy(&relativeOffsetFunc, elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, 4);
relativeOffsetFunc += (elfinfo.tempOffsetTable + (elfinfo.tempOffsetCounter *ThunkTrampolineSize))-(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset);
memcpy(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, &relativeOffsetFunc, 4);
#else
DEBUG_PRINT("ERROR: Not configured for this architecture\n");
#endif
/* Once set increment the Thunk Trampoline counter to the next one */
elfinfo.tempOffsetCounter+=1;
}
else if (elfinfo.sectHeader[counter].sh_flags== 0x40){
/* Handle the relocations for values and functions included in the object file */
/* NOTE: If sh_flags == 0x40, then sh_info contains the section the relocation applies too */
#if defined(__amd64__) || defined(__x86_64__)
int32_t relativeOffset = (elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx])-(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset)+rel[c2].r_addend + elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_value;
#elif defined(__i386__)
int32_t relativeOffset = 0;
if (ELF_R_TYPE(rel[c2].r_info) == R_386_32){
DEBUG_PRINT("\t\t32bit Direct\n");
memcpy(&relativeOffset, elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, 4);
//relativeOffset = (elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx])-(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset)+relativeOffset + elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_value;
relativeOffset += elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_value;
relativeOffset += (int32_t)(elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx]);
}
else if (ELF_R_TYPE(rel[c2].r_info) == R_386_PC32){
DEBUG_PRINT("\t\tPC relative Address\n");
memcpy(&relativeOffset, elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, 4);
relativeOffset = (elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx])-(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset)+relativeOffset + elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_value;
}
#else
int32_t relativeOffset = 0;
#endif
DEBUG_PRINT("\t\tFirstAddress(NoAddend): %p\n", (elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx]));
#if defined(__amd64__) || defined(__x86_64__)
DEBUG_PRINT("\t\tFirstAddress: %p\n", (elfinfo.sectionMappings[elfinfo.symbolTable[ELF_R_SYM(rel[c2].r_info)].st_shndx]+rel[c2].r_addend));
#endif
DEBUG_PRINT("\t\tSecondAddress(NoOffset): %p\n", (elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]));
DEBUG_PRINT("\t\tSecondAddress: %p\n", (elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset));
DEBUG_PRINT("\t\tRelativeOffset: 0x%x\n", relativeOffset);
/* Copy over the relative offset of the value to the section+offset */
memcpy(elfinfo.sectionMappings[elfinfo.sectHeader[counter].sh_info]+rel[c2].r_offset, &relativeOffset, 4);
}
DEBUG_PRINT("\t\tInfo: 0x%lx\n", rel[c2].r_info);
DEBUG_PRINT("\t\tOffset: 0x%lx\n", rel[c2].r_offset);
#if defined(__amd64__) || defined(__x86_64__)
DEBUG_PRINT("\t\tAddend: 0x%lx\n", rel[c2].r_addend);
#endif
DEBUG_PRINT("\t\t----------------------------------------------------------\n");
}
}
/* Handle the symbols here, get the entry points and all that */
if (elfinfo.sectHeader[counter].sh_type == SHT_SYMTAB){
for (c2 = 0; c2 < elfinfo.sectHeader[counter].sh_size / sizeof(Elf_Sym); c2 += 1){
Elf_Sym* syms = (Elf_Sym*)(elfObjectData + elfinfo.sectHeader[counter].sh_offset);
//DEBUG_PRINT("\t\t0x%x\n", syms[c2].st_name);
DEBUG_PRINT("\t\tSymbolName: %s\n", elfinfo.stringTable + syms[c2].st_name);
if (strcmp(functionName, elfinfo.stringTable + syms[c2].st_name) == 0){
DEBUG_PRINT("\t\t\tFOUND GO!\n");
ptr = (int (*)(unsigned char *, int))elfinfo.sectionMappings[syms[c2].st_shndx] + syms[c2].st_value;
}
DEBUG_PRINT("\t\tSymbolSectionIndex: %d\n", syms[c2].st_shndx);
if (elfinfo.sectionMappings != NULL && syms[c2].st_shndx < elfinfo.sectHeaderSize && syms[c2].st_shndx != 0){
DEBUG_PRINT("\t\tSymbolAddress(real): %p\n", elfinfo.sectionMappings[syms[c2].st_shndx] + syms[c2].st_value);
}
}
}
}
DEBUG_PRINT("TempOffsetTable: %p\n", elfinfo.tempOffsetTable);
#ifdef WIN32
DEBUG_PRINT("Skipping mprotect code for windows, already executable.\n");
#else
if (mprotect(elfinfo.tempOffsetTable, 255*ThunkTrampolineSize, PROT_READ | PROT_EXEC) != 0){
DEBUG_PRINT("Failed to mprotect the thunk table\n");
}
#endif
/* TODO: Set all the permissions of the sectionMappings, sectionMappingProts, and tempOffsetTable */
for (counter = 0; counter < elfinfo.sectHeaderSize; counter++){
DEBUG_PRINT("Section #%d mapped at %p\n", counter, elfinfo.sectionMappings[counter]);
if (elfinfo.sectionMappings[counter] != NULL){
#ifdef WIN32
DEBUG_PRINT("Not doing mprotect for windows, already executable.\n");
#else
if (mprotect(elfinfo.sectionMappings[counter], elfinfo.sectHeader[counter].sh_size, elfinfo.sectionMappingProts[counter]) != 0){
DEBUG_PRINT("Failed to protect memory\n");
}
#endif
}
}
DEBUG_PRINT("Trying to run ptr......\n");
/* NOTE: Change this to pass in arguments for ones that use it */
(void)ptr(argumentdata, argumentSize);
DEBUG_PRINT("Returned from ptr\n");
cleanup:
DEBUG_PRINT("Cleaning up...\n");
for (counter = 0; counter < elfinfo.sectHeaderSize; counter++){
DEBUG_PRINT("Freeing Section #%d\n", counter);
if (elfinfo.sectionMappings != NULL){
if (elfinfo.sectionMappings[counter] != NULL){
#ifdef WIN32
VirtualFree(elfinfo.sectionMappings[counter], 0, MEM_RELEASE);
#else
if (munmap(elfinfo.sectionMappings[counter], elfinfo.sectHeader[counter].sh_size) != 0){
DEBUG_PRINT("Failed to unmap memory\n");
}
#endif
}
}
}
if (elfinfo.tempOffsetTable){
#ifdef WIN32
VirtualFree(elfinfo.tempOffsetTable, 0, MEM_RELEASE);
#else
munmap(elfinfo.tempOffsetTable, 255*ThunkTrampolineSize);
#endif
}
if (elfinfo.sectionMappings){
free(elfinfo.sectionMappings);
}
if (elfinfo.sectionMappingProts){
free(elfinfo.sectionMappingProts);
}
goto retlab;
retlab:
DEBUG_PRINT("Returning\n");
return retcode;
errorcase:
DEBUG_PRINT("ERRORCASE!!!!\n");
goto cleanup;
#else
return -1;
#endif /* Wrapper ifdef for supported arch's */
}
#ifdef TESTING_MAIN
int main(int argc, char** argv, char** envp)
{
//int (*ptr)(char*, int*);
unsigned char* buf = NULL;
int size = 0;
FILE* elf = NULL;
int checkcode = 0;
char* outputdata = NULL;
char* argumentdata = NULL;
int argumentdatalen = 0;
int outputdataLen = 0;
if (argc < 2){
printf("%s ./path/to/objectfile.o\n", argv[0]);
return 0;
}
elf = fopen(argv[1], "rb");
if (elf == NULL){
printf("ERROR: File doesn't exist\n");
return 0;
}
fseek(elf, 0, SEEK_END);
size = ftell(elf);
fseek(elf, 0, SEEK_SET);
buf = calloc(size, 1);
if (buf == NULL){
return 0;
}
(void)fread(buf, 1, size, elf);
argumentdata = (char*)unhexlify((unsigned char*)argv[2], &argumentdatalen);
checkcode = ELFRunner("go", buf, size, (unsigned char*)argumentdata, argumentdatalen );
if (checkcode == 0){
outputdata = BeaconGetOutputData(&outputdataLen);
printf("Output data : %s\n", outputdata);
free(outputdata);
}
free(buf);
fclose(elf);
return 0;
}
#endif
+314
View File
@@ -0,0 +1,314 @@
/*
* Cobalt Strike 4.X BOF compatibility layer
* -----------------------------------------
* The whole point of these files are to allow beacon object files built for CS
* to run fine inside of other tools without recompiling.
*
* Built off of the beacon.h file provided to build for CS.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdarg.h>
#include <string.h>
#ifndef WIN32
#include <sys/mman.h>
#include <dlfcn.h>
#else
#include <windows.h>
#endif
#include "beacon_compatibility.h"
#define X86PATH "System32"
#define X64PATH "sysnative"
#ifdef __APPLE__
#define INTERNAL_DEFAULT_LIBRARY ((void*) -2)
#else
#define INTERNAL_DEFAULT_LIBRARY NULL
#endif
extern char** environ;
/* Data Parsing */
beacon_function_t BeaconInternalMapping[17] = {
{"BeaconDataParse", (void*)BeaconDataParse},
{"BeaconDataInt", (void*)BeaconDataInt},
{"BeaconDataShort", (void*)BeaconDataShort},
{"BeaconDataLength", (void*)BeaconDataLength},
{"BeaconDataExtract", (void*)BeaconDataExtract},
{"BeaconFormatAlloc", (void*)BeaconFormatAlloc},
{"BeaconFormatReset", (void*)BeaconFormatReset},
{"BeaconFormatFree", (void*)BeaconFormatFree},
{"BeaconFormatAppend", (void*)BeaconFormatAppend},
{"BeaconFormatPrintf", (void*)BeaconFormatPrintf},
{"BeaconFormatToString", (void*)BeaconFormatToString},
{"BeaconFormatInt", (void*)BeaconFormatInt},
{"BeaconPrintf", (void*)BeaconPrintf},
{"BeaconOutput", (void*)BeaconOutput},
{"BeaconIsAdmin", (void*)BeaconIsAdmin},
{"getEnviron", (void*)getEnviron}
};
char** getEnviron(void){
return environ;
}
#ifdef _WIN32
/* A hacky compatible dlsym function for use on windows systems.
* TODO: Implement a internal function lookup function for all OS's that
* will lookup internal functions, and global functions.*/
void *dlsym(void *handle, const char *symbol){
static HMODULE DefaultHandle = NULL;
void* PointerValue = NULL;
if (handle == INTERNAL_DEFAULT_LIBRARY && DefaultHandle == NULL){
DefaultHandle = LoadLibraryA("msvcrt.dll");
}
if (DefaultHandle != NULL){
PointerValue = GetProcAddress(DefaultHandle, symbol);
}
return PointerValue;
}
#endif
void* internalFunctionLookup(char* symbolName){
void* functionaddress = NULL;
int tempcounter = 0;
for (tempcounter = 0; tempcounter < BEACONINTERNALMAPPINGCOUNT; tempcounter++){
if (strcmp(symbolName, BeaconInternalMapping[tempcounter].functionName) == 0){
#ifdef DEBUG
printf("\t\tInternalFunction: %s\n", symbolName);
#endif
functionaddress = BeaconInternalMapping[tempcounter].function;
return functionaddress;
}
}
/* If not an internal function, then its an external one */
if (functionaddress == NULL){
functionaddress = dlsym(INTERNAL_DEFAULT_LIBRARY, symbolName);
}
return functionaddress;
}
uint32_t swap_endianess(uint32_t indata){
uint32_t testint = 0xaabbccdd;
uint32_t outint = indata;
if (((unsigned char*)&testint)[0] == 0xdd){
((unsigned char*)&outint)[0] = ((unsigned char*)&indata)[3];
((unsigned char*)&outint)[1] = ((unsigned char*)&indata)[2];
((unsigned char*)&outint)[2] = ((unsigned char*)&indata)[1];
((unsigned char*)&outint)[3] = ((unsigned char*)&indata)[0];
}
return outint;
}
char* beacon_compatibility_output = NULL;
int beacon_compatibility_size = 0;
int beacon_compatibility_offset = 0;
void BeaconDataParse(datap* parser, char* buffer, int size){
if (parser == NULL){
return;
}
parser->original = buffer;
parser->buffer = buffer;
parser->length = size-4;
parser->size = size-4;
parser->buffer += 4;
return;
}
int BeaconDataInt(datap* parser){
int32_t fourbyteint = 0;
if (parser->length < 4){
return 0;
}
memcpy(&fourbyteint, parser->buffer, 4);
parser->buffer += 4;
parser->length -= 4;
return (int)fourbyteint;
}
short BeaconDataShort(datap* parser){
int16_t retvalue = 0;
if (parser->length < 2){
return 0;
}
memcpy(&retvalue, parser->buffer, 2);
parser->buffer += 2;
parser->length -= 2;
return (short)retvalue;
}
int BeaconDataLength(datap* parser){
return parser->length;
}
char* BeaconDataExtract(datap* parser, int* size){
uint32_t length = 0;
char* outdata = NULL;
/*Length prefixed binary blob, going to assume uint32_t for this.*/
if (parser->length < 4){
return NULL;
}
memcpy(&length, parser->buffer, 4);
parser->buffer += 4;
outdata = parser->buffer;
if (outdata == NULL){
return NULL;
}
parser->length -=4;
parser->length -= length;
parser->buffer += length;
if (size != NULL && outdata != NULL){
*size = length;
}
return outdata;
}
/* format API */
void BeaconFormatAlloc(formatp* format, int maxsz){
if (format == NULL){
return;
}
format->original = calloc(maxsz, 1);
format->buffer = format->original;
format->length = 0;
format->size = maxsz;
return;
}
void BeaconFormatReset(formatp* format){
memset(format->original, 0, format->size);
format->buffer = format->original;
format->length = format->size;
return;
}
void BeaconFormatFree(formatp* format){
if (format == NULL){
return;
}
if (format->original){
free(format->original);
format->original = NULL;
}
format->buffer = NULL;
format->length = 0;
format->size = 0;
return;
}
void BeaconFormatAppend(formatp* format, char* text, int len){
memcpy(format->buffer, text, len);
format->buffer+= len;
format->length+= len;
return;
}
void BeaconFormatPrintf(formatp* format, char* fmt, ...){
/*Take format string, and sprintf it into here*/
va_list args;
int length = 0;
va_start (args, fmt);
length = vsnprintf(NULL, 0, fmt, args);
va_end(args);
if (format->length + length > format->size){
return;
}
va_start (args, fmt);
(void)vsnprintf(format->buffer, length, fmt, args);
va_end(args);
format->length += length;
format->buffer+= length;
return;
}
char* BeaconFormatToString(formatp* format, int* size){
*size = format->length;
return format->original;
}
void BeaconFormatInt(formatp* format, int value){
uint32_t indata = value;
uint32_t outdata = 0;
if (format->length + 4 > format->size){
return;
}
outdata = swap_endianess(indata);
memcpy(format->buffer, &outdata, 4);
format->length += 4;
format->buffer += 4;
return;
}
/* Main output functions */
void BeaconPrintf(int type, char* fmt, ...){
/* Change to maintain internal buffer, and return after done running. */
int length = 0;
char* tempptr = NULL;
va_list args;
#ifdef DEBUG
va_start (args, fmt);
vprintf(fmt, args);
va_end(args);
#endif
va_start (args, fmt);
length = vsnprintf(NULL, 0, fmt, args)+1;
va_end(args);
tempptr = realloc(beacon_compatibility_output, beacon_compatibility_size+length+1);
if (tempptr == NULL){
return;
}
beacon_compatibility_output = tempptr;
memset(beacon_compatibility_output+beacon_compatibility_offset, 0, length+1);
va_start (args, fmt);
length = vsnprintf(beacon_compatibility_output+beacon_compatibility_offset, length, fmt, args);
beacon_compatibility_size+=length;
beacon_compatibility_offset+=length;
va_end(args);
return;
}
void BeaconOutput(int type, char* data, int len){
char* tempptr = NULL;
tempptr = realloc(beacon_compatibility_output, beacon_compatibility_size+len+1);
beacon_compatibility_output = tempptr;
if (tempptr == NULL){
return;
}
memset(beacon_compatibility_output+beacon_compatibility_offset, 0, len+1);
memcpy(beacon_compatibility_output+beacon_compatibility_offset, data, len);
beacon_compatibility_size+=len;
beacon_compatibility_offset+=len;
return;
}
int BeaconIsAdmin(void){
/* Leaving this to be implemented by people needing it */
#ifdef DEBUG
printf("BeaconIsAdmin Called\n");
#endif
return 0;
}
char* BeaconGetOutputData(int *outsize){
char* outdata = beacon_compatibility_output;
*outsize = beacon_compatibility_size;
beacon_compatibility_output = NULL;
beacon_compatibility_size = 0;
beacon_compatibility_offset = 0;
return outdata;
}
+39
View File
@@ -0,0 +1,39 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include "beacon_api.h"
#define PATH_MAX 2048
int test3(void){
printf("This is the test3 function\n");
return 0;
}
int go(char* indata, int* outlen){
char* pwdOutput = NULL;
char* testptr = NULL;
pwdOutput = calloc(PATH_MAX+1, 1);
BeaconPrintf(CALLBACK_OUTPUT, "UID: %d EUID: %d\n", getuid(), geteuid());
if (pwdOutput != NULL){
testptr = getcwd(pwdOutput, PATH_MAX);
if (testptr != NULL){
BeaconPrintf(CALLBACK_OUTPUT, "Current Working Directory: %s\n", testptr);
}
}
if (getuid() == 0){
BeaconPrintf(CALLBACK_OUTPUT, "Running as root!!!!\n");
}
else{
BeaconPrintf(CALLBACK_OUTPUT, "Running as a standard user.\n");
}
if (pwdOutput){
free(pwdOutput);
}
return 0;
}
+16
View File
@@ -0,0 +1,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include "beacon_api.h"
int test1(void){
printf("This is a test2\n");
return 0;
}
int go(char* indata, int* outlen){
BeaconPrintf(CALLBACK_OUTPUT, "This is a test BeaconPrintf output\n");
printf("This is a test\n");
return 0;
}
+19
View File
@@ -0,0 +1,19 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
int go(char* indata, int* outlen){
printf("This is a test\n");
printf("UID is: %d\n", getuid());
printf("This is another test\n");
if (getuid() > 500){
printf("Yep its greater than 500\n");
}
else{
printf("Nope it isn't\n");
}
return 0;
}
+37
View File
@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
int test1(void){
printf("This is the test1 function\n");
return 0;
}
int test2(void){
printf("This is the test2 function\n");
return 0;
}
int test3(void){
printf("This is the test3 function\n");
return 0;
}
int go(char* indata, int* outlen){
(void)test1();
(void)test2();
(void)test3();
printf("This is a test\n");
printf("UID is: %d\n", getuid());
printf("This is another test\n");
if (getuid() > 500){
printf("Yep its greater than 500\n");
}
else{
printf("Nope it isn't\n");
}
return 0;
}