Skip to content
Jonathan Brossard edited this page Aug 12, 2016 · 3 revisions

wsh : The Witchcraft shell

The witchcraft shell accepts ELF shared libraries, ELF ET_DYN executables and Witchcraft Shell Scripts written in Punk-C as an input. It loads all the executables in its own address space and make their API available for programming in its embedded interpreter. This provides for binaries functionalities similar to those provided via reflection on languages like Java.

wsh command line options

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

Options:

    -x, --args                Optional script argument separator.
    -v, --verbose
    -V, --version

Script:

    If the first argument is an existing file which is not a known binary file format,
    it is assumed to be a lua script and gets executed.

Binaries:

    Any binary file name before the -x tag gets loaded before running the script.
    The last binary loaded is the main binary analyzed.

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 retreive its banner and displays it within the wsh intterpreter.

jonathan@blackbox:~$ wsh /usr/sbin/apache2
> a = ap_get_server_banner()
> print(a)
Apache/2.4.7
> 

To get help at any time from the wsh interpreter, simply type help. To get help on a particular topic, type help("topic").

The following example illustrates how to display the main wsh help from the interpreter and how to get detailed help on the grep command by calling help("grep") from the wsh interpreter.

> help
  [Shell commands]

	help, quit, exit, shell, exec, clear

  [Functions]

 + basic:
	help(), man()

 + memory display:
	 hexdump(), hex_dump(), hex()

 + memory maps:
	shdrs(), phdrs(), map(), procmap(), bfmap()

 + symbols:
	symbols(), functions(), objects(), info(), search(), headers()

 + memory search:
	grep(), grepptr()

 + load libaries:
	loadbin(), libs(), entrypoints(), rescan()

 + code execution:
	libcall()

 + buffer manipulation:
	xalloc(), ralloc(), xfree(), balloc(), bset(), bget(), rdstr(), rdnum()

 + control flow:
	 breakpoint(), bp()

 + system settings:
	enableaslr(), disableaslr()

 + settings:
	 verbose(), hollywood()

 + advanced:
	ltrace()

Try help("cmdname") for detailed usage on command cmdname.

> help("grep")

	WSH HELP FOR FUNCTION grep


NAME

	grep

SYNOPSIS

	table match = grep(<pattern>, [patternlen], [dumplen], [before])

DESCRIPTION

	Search <pattern> in all ELF sections in memory. Match [patternlen] bytes, then display [dumplen] bytes, optionally including [before] bytes before the match. Results are displayed in enhanced decimal form

RETURN VALUES

	Returns 1 lua table containing matching memory addresses.


> 

Extending wsh with Witchcraft Shell Scripts

The combination of a full lua interpreter in the same address space as the loaded executables and shared libraries in combination with the reflection like capabilities of wsh allow to call any function loaded in the address space from the wsh interpreter transparently. The resulting API, a powerfull combination of lua and C API is called Punk-C. Wsh is fully scriptable in Punk-C, and executes Punk-C on the fly via its dynamic interpreter. Scripts in Punk C can be invoked by specifying the full path to wsh in the magic bytes of a wsh shell. The following command displays the content of a Witchcraft shell script:

jonathan@blackbox:/usr/share/wcc/scripts$ cat md5.wsh
#!/usr/bin/wsh

-- Computing a MD5 sum using cryptographic functions from foreign binaries (eg: sshd/OpenSSL)

function str2md5(input)

	out = calloc(33, 1)
	ctx = calloc(1024, 1)

	MD5_Init(ctx)
	MD5_Update(ctx, input, strlen(input))
	MD5_Final(out, ctx)

	free(ctx)
	return out
end

input = "Message needing hashing\n"
hash = str2md5(input)
hexdump(hash,16)

exit(0)
jonathan@blackbox:/usr/share/wcc/scripts$ 

To run this script using the API made available inside the address space of sshd, simply run:

jonathan@blackbox:/usr/share/wcc/scripts$ ./md5.wsh /usr/sbin/sshd 
0x43e8b280    d6 fc 46 91 b0 6f ab 75 4d 9c a7 58 6d 9c 7e 36    V|F.0o+uM.'Xm.~6
jonathan@blackbox:/usr/share/wcc/scripts$ 

Limits of wsh

wsh can only load shared libraries and ET_DYN dynamically linked ELF executables directly. This means ET_EXEC executables may need to be libified using wld before use in wsh. Binaries in other file formats might need to be turned into ELF files using wcc.

Analysing and Executing ARM/SPARC/MIPS binaries "natively" on Intel x86_64 cpus via JIT binary translation

wsh can be cross compiled to ARM, SPARC, MIPS and other plateforms and used in association with the qemu's user space emulation mode to provide JIT binary translation on the fly and analyse shared libraries and binaries from other cpus without requiring emulation a full operating system in a virtual machine. On the the analyzed binaries are translated from one CPU to an other, and the analysed binaries, the wsh cross compiled analyser and the qemu binary translator share the address space of a single program. This significantly diminishes the complexity of analysing binaries accross different hardware by seemingly allowing to run ARM or SPARC binaries on a linux x86_64 machine natively and transparently.

Contribute

The Witchcraft Compiler Collection is Licensed under the MIT License.

Feel free to contribute :)

Clone this wiki locally