Skip to content

Commit

Permalink
Improved README.md and installation instructions.
Browse files Browse the repository at this point in the history
Allow hardened compilation.
Added convenience functions to produce pointers from objects.
  • Loading branch information
endrazine committed May 27, 2024
1 parent d09ff7c commit 0bbdd7b
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 36 deletions.
13 changes: 12 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,23 @@
# This file is licensed under MIT License.
#

CFLAGS := -W -Wall -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-parameter -Wno-unused-function -Wno-unused-result -fpie -pie -fPIC -g3 -ggdb -I../../include -I./include/sflib/ -I./include -I../../include/ -Wno-incompatible-pointer-types -fstack-protector-all -Wl,-z,relro,-z,now -DPACKAGE -DPACKAGE_VERSION -masm=intel -rdynamic -D_FORTIFY_SOURCE=2 -O2
COMPILER_VERSION := $(shell $(CC) --version)
ifneq '' '$(findstring clang,$(COMPILER_VERSION))'
ASAN := -fsanitize=address -static-libsan
else
ASAN := -fsanitize=address -static-libasan
endif

CFLAGS := -W -Wall -Wno-discarded-qualifiers -Wno-int-conversion -Wno-unused-parameter -Wno-unused-function -Wno-unused-result -fpie -pie -fPIC -g3 -ggdb -I../../include -I./include/sflib/ -I./include -I../../include/ -Wno-incompatible-pointer-types -fstack-protector-all -Wl,-z,relro,-z,now -DPACKAGE -DPACKAGE_VERSION -masm=intel -rdynamic -D_FORTIFY_SOURCE=2 -O2


all:
mkdir -p bin
cd src && make CFLAGS=" $(CFLAGS)"

asan: CFLAGS += $(ASAN)
asan: all

documentation:
cd src && doxygen ./tex/project.cfg
cd doc/latex && make && cp refman.pdf ../WCC_internal_documentation.pdf
Expand Down
43 changes: 16 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,23 +19,9 @@ The Witchcraft Compiler Collection requires the following software to be install
capstone, glibc, libbfd, libdl, zlib, libelf, libreadline, libgsl, make

### Installation Requirements on Ubuntu/Debian
Under Ubuntu/Debian those dependencies can be installed with the following commands (tested on Ubuntu 14.04):
Under Ubuntu/Debian those dependencies can be installed with the following commands (tested on Ubuntu 22.04):

# Required for add-apt-repository
sudo apt-get install python-software-properties software-properties-common

# Add repo for clang
sudo add-apt-repository ppa:kxstudio-team/builds
sudo apt-get update

# Install dependencies
sudo apt-get install binutils-dev clang libelf-dev libgsl0-dev libiberty-dev libreadline6 libreadline6-dev make uthash-dev

# Install latest capstone and capstone-dev from "Ubuntu 14.04 - DEB packages" http://www.capstone-engine.org/download.html
wget http://www.capstone-engine.org/download/3.0.4/ubuntu-14.04/libcapstone3_3.0.4-0.1ubuntu1_amd64.deb
sudo dpkg -i libcapstone3_3.0.4-0.1ubuntu1_amd64.deb
wget http://www.capstone-engine.org/download/3.0.4/ubuntu-14.04/libcapstone-dev_3.0.4-0.1ubuntu1_amd64.deb
sudo dpkg -i libcapstone-dev_3.0.4-0.1ubuntu1_amd64.deb
sudo apt-get install -y clang libbfd-dev uthash-dev libelf-dev libcapstone-dev libreadline-dev libiberty-dev libgsl-dev build-essential git debootstrap file

## Building and Installing:

Expand Down Expand Up @@ -76,14 +62,13 @@ The following commands constitute the core of the Witchcraft Compiler Collection
wld takes an ELF executable as an input and modifies it to create a shared library.
#### wld command line options
jonathan@blackbox:~$ wld
Witchcraft Compiler Collection (WCC) version:0.0.1 (23:11:13 Jul 21 2016)

Usage: wld [options] file

options:
Witchcraft Compiler Collection (WCC) version:0.0.6 (18:10:51 May 10 2024)

-libify Set Class to ET_DYN in input ELF file.
Usage: wld -libify [-noinit] file

Options:
-libify Transform executable into shared library.
-noinit Ignore constructors and desctructors in output library.
jonathan@blackbox:~$
#### Example usage of wld
The following example libifies the executable /bin/ls into a shared library named /tmp/ls.so.
Expand All @@ -100,7 +85,7 @@ The wcc compiler takes binaries (ELF, PE, ...) as an input and creates valid ELF

#### wcc command line options
jonathan@blackbox:~$ wcc
Witchcraft Compiler Collection (WCC) version:0.0.1 (01:47:53 Jul 29 2016)
Witchcraft Compiler Collection (WCC) version:0.0.6 (18:10:50 May 10 2024)

Usage: wcc [options] file

Expand All @@ -125,6 +110,7 @@ The wcc compiler takes binaries (ELF, PE, ...) as an input and creates valid ELF
-v, --verbose
-V, --version


jonathan@blackbox:~$

#### Example usage of wcc
Expand All @@ -148,13 +134,15 @@ The witchcraft shell accepts ELF shared libraries, ELF ET_DYN executables and Wi
#### wsh command line options

jonathan@blackbox:~$ wsh -h
Usage: wsh [script] [options] [binary1] [binary2] ... [-x] [script_arg1] [script_arg2] ...
Usage: wsh [script] [-h|-q|-v|-V|-g] [binary1] [binary2] ... [-x [script_arg1] [script_arg2] ...]

Options:

-x, --args Optional script argument separator.
-v, --verbose
-V, --version
-x, --args Optional script argument separator
-q, --quiet Display less output
-v, --verbose Display more output
-g, --global Bind symbols globally
-V, --version Display version and build, then exit

Script:

Expand All @@ -168,6 +156,7 @@ The witchcraft shell accepts ELF shared libraries, ELF ET_DYN executables and Wi

jonathan@blackbox:~$


#### Example usage of wsh
The following command loads the /usr/sbin/apache2 executable within wsh, calls the ap_get_server_banner() function within
apache to retrieve its banner and displays it within the wsh interpreter.
Expand Down
2 changes: 2 additions & 0 deletions src/wsh/include/libwitch/wsh.h
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,8 @@ static int shdrs(lua_State * L);
static int verbose(lua_State * L);
static int xalloc(lua_State * L);
static int ralloc(lua_State * L);
static int getptr(lua_State * L);
static int mkptr(lua_State * L);

static int headers(lua_State * L);
static int prototypes(lua_State * L);
Expand Down
8 changes: 6 additions & 2 deletions src/wsh/include/libwitch/wsh_functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ char *default_options[] = {
"script",
"enablecore",
"disablecore",
"gencore"
"gencore",
"getptr",
"mkptr"
};

// All lua 5.3 Functions and global variables
Expand Down Expand Up @@ -382,7 +384,9 @@ tuple_t exposed[] = {
{wsh_appear, "appear"},
{wsh_hide, "hide"},
{wsh_appear, "unhide"},
{wsh_hide, "unappear"}
{wsh_hide, "unappear"},
{getptr, "getptr"},
{mkptr, "mkptr"}
};

range_t ranges[] = {
Expand Down
176 changes: 170 additions & 6 deletions src/wsh/wsh.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,26 @@
#include <uthash.h>
#include <utlist.h>
#include <libgen.h> // For basename()
#include <lauxlib.h>

// address sanitizer macro : disable a function by prepending ATTRIBUTE_NO_SANITIZE_ADDRESS to its definition
#if defined(__clang__) || defined (__GNUC__)
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address))
# define ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) __attribute__((disable_sanitizer_instrumentation))
#else
# define ATTRIBUTE_NO_SANITIZE_ADDRESS
#endif

#if defined(__has_feature)
# if __has_feature(address_sanitizer) // clang
# define __SANITIZE_ADDRESS__ // GCC
# endif
#endif

#if defined(__SANITIZE_ADDRESS__)
#define HAS_ASAN 1
#endif


#ifndef __amd64__
#define REG_RIP 16
#endif
Expand Down Expand Up @@ -2226,6 +2238,35 @@ void print_syscall(pid_t child, int syscall_req) {
}
*/

#ifdef HAS_ASAN
ATTRIBUTE_NO_SANITIZE_ADDRESS
size_t mystrlen(char *ptr)
{
unsigned int ret = 0;

while(ptr[ret] != 0){ ret++;}

return ret;
}

ATTRIBUTE_NO_SANITIZE_ADDRESS
void *mymemset(void *s, int c, size_t n)
{
unsigned int i = 0;
char *ptr = 0;

ptr = s;
for(i = 0; i < n ; i++){
ptr[i] = c;
}

return s;
}
#else
#define mystrlen strlen
#define mymemset memset
#endif

/**
* Main wrapper around a library call.
* This function returns 9 values: ret (returned by library call), errno, firstsignal, total number of signals, firstsicode, firsterrno, faultaddr, reason, context
Expand Down Expand Up @@ -2388,17 +2429,21 @@ static int libcall(lua_State * L)

// is it a string ?
char *ptr = ret;
for (j = 0; j < strlen(ret); j++) {
for (j = 0; j < mystrlen(ret); j++) {
if (!isascii((ptr[j]))) {
notascii = 1;
break;
}
}

#ifdef HAS_ASAN
if ((!notascii)&&(mystrlen(ret) >= 1)) {
#else
if (!notascii) {
#endif
lua_pushstring(L, ret); // Ascii : push string
} else {
lua_pushinteger(L, ret); // Push as a number
lua_pushinteger(L, ret);// Push as a number
}
} else {
lua_pushinteger(L, ret); // Push as a number
Expand Down Expand Up @@ -4084,10 +4129,10 @@ int ralloc(lua_State * L)

mprotect(ptr, sz, PROT_EXEC | PROT_READ | PROT_WRITE);

memset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
mymemset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
global_xalloc++;

memset(ptr,poison, size % 4096);
mymemset(ptr,poison, size % 4096);

mprotect(ptr, sz, PROT_READ);

Expand Down Expand Up @@ -4143,7 +4188,7 @@ int xalloc(lua_State * L)

mprotect(ptr, sz, PROT_EXEC | PROT_READ | PROT_WRITE);

memset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
mymemset(ptr, poison ? poison : default_poison + global_xalloc, sz); // map with default poison bytes
global_xalloc++;

if(!poison){ // If autoref, overwrite all the content with address of our own buffer
Expand Down Expand Up @@ -5604,3 +5649,122 @@ static void initialize_wsh() {
setenv("MALLOC_CHECK_", "3", 1);
}


/**
* Methods for manipulating arrays of strings from lua
*
// metatable method for handling "array[index]"
static int array_index (lua_State* L) {
int** parray = luaL_checkudata(L, 1, "array");
int index = luaL_checkinteger(L, 2);
lua_pushnumber(L, (*parray)[index-1]);
return 1;
}
// metatable method for handle "array[index] = value"
static int array_newindex (lua_State* L) {
int** parray = luaL_checkudata(L, 1, "array");
int index = luaL_checkinteger(L, 2);
int value = luaL_checkinteger(L, 3);
(*parray)[index-1] = value;
return 0;
}
void luaL_openlib(lua_State *L, const char *libname, const luaL_Reg *l, int nup) {
if ( libname ) {
lua_getglobal(L, libname);
if (lua_isnil(L, -1)) {
lua_pop(L, 1);
lua_newtable(L);
}
}
luaL_setfuncs(L, l, 0);
if ( libname ) lua_setglobal(L, libname);
}
// create a metatable for our array type
static void create_array_type(lua_State* L) {
static const struct luaL_reg array[] = {
{ "__index", array_index },
{ "__newindex", array_newindex },
NULL, NULL
};
luaL_newmetatable(L, "array");
luaL_openlib(L, NULL, array, 0);
}
// expose an array to lua, by storing it in a userdata with the array metatable
static int expose_array(lua_State* L, int array[]) {
int** parray = lua_newuserdata(L, sizeof(int**));
*parray = array;
luaL_getmetatable(L, "array");
lua_setmetatable(L, -2);
return 1;
}
// test data
int mydata[] = { 1, 2, 3, 4 };
// test routine which exposes our test array to Lua
static int getarray (lua_State* L) {
return expose_array( L, mydata );
}
int luaopen_array (lua_State* L) {
create_array_type(L);
// make our test routine available to Lua
lua_register(L, "array", getarray);
return 0;
}
*/





/**
* Get a pointer to a variable
*/
int getptr(lua_State * L)
{
char *vname = 0;

read_arg1(vname);
if(!vname){
printf("ERROR: missing name of variable\n");
return 0;
}

lua_pushlightuserdata(L, vname);

return 1;
}

/**
* Create a pointer to a variable
*/
int mkptr(lua_State * L)
{
char *vname = 0;
char **newptr = 0;

read_arg1(vname);
if(!vname){
printf("ERROR: missing name of variable\n");
return 0;
}

newptr = calloc(1, sizeof(char*));
newptr[0] = vname;

lua_pushinteger(L, newptr);

return 1;
}


0 comments on commit 0bbdd7b

Please sign in to comment.