mirror of
https://github.com/trustedsec/ELFLoader
synced 2026-06-08 17:56:51 +00:00
Initial commit
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
*.o
|
||||
*.out
|
||||
@@ -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
|
||||
@@ -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
|
||||
```
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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()
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user