400 likes | 464 Views
ShellForth. Shell-code cross-compiler for Forth Dave Weinstein / ToorCon 16. Agenda. ShellForth in Practice. Code Generation. Forth Overview. Intro. Who am I? Forth? Seriously?. Intro. Who am I? Dave Weinstein Long-time software developer
E N D
ShellForth Shell-code cross-compiler for Forth Dave Weinstein / ToorCon 16
Agenda • ShellForth in Practice • Code Generation • Forth Overview Intro • Who am I? • Forth? Seriously?
Intro • Who am I? • Dave Weinstein • Long-time software developer • Moved into the security space (as other than “the problem”) about a decade ago • Currently a Security Researcher at the Zero Day Initiative in HP Security Research Forth? Shell-code in Forth? Seriously? Yes. Ok, no. Well, yes and no. • It started out as a joke concept (code that never came from a standard compiler for RE questions) • It turned out to be interesting in and of itself • Also, back in the 1980s, I burned out my “technical religious fanatic” circuits as a Forth ideologue
Agenda • Forth Overview • Code Generation • ShellForth in Practice Intro • Who am I? • Forth? Seriously? • History • Basics • Key Features • Use cases
Forth Overview • History of Forth • Created by Charles Moore • Original development work dates back to the 1950s • Key language concepts show up by the late 1960s, with a recognizably Forth language by 1970 • Language as “usable by people other than Charles Moore” dates back to the 1970s • ANSI Standard defined in 1994 • ShellForth is not an ANSI-compliant dialect • In fact, the ANSI-compliant dialects won’t even talk to it at parties
Forth Overview • Forth Basics • Stack based language • All Forth subroutines (“words”) consume arguments from the stack, and leave results on the stack • Returning multiple values has always been trivial in Forth • One stack isn’t enough • Forth has a separate “return stack”, which holds the return address for ending a subroutine, but can also be used to hold information inside of a subroutine • Syntax is almost always “Reverse-Polish Notation” • i.e. “5 4 +” instead of “5 + 4” or “(+ 5 4)” • No, my fondness for Forth and RPN is not why I ended up at Hewlett-Packard
Forth Overview • Forth Basics • Based around a dictionary of “words” • Each word has an action associated with it • Variables put their address on the data stack • Constants put their value on the data stack • Executable words (i.e. subroutines) execute their body • Forth intrinsics are not privileged • New “defining words” (words that create new types of words) can be defined • Existing words (including Forth core language features) can be overridden for future compilation (already-compiled uses are unaffected)
Forth Overview • Programming in Forth • Often derided as a “write-only language” • Idiomatic Forth programming consists of effectively extending the language until it includes your application, and then stopping • Forth syntax leads to a large number of small functions with few side effects • All of the needed linguistic features for Function Programming have always been part of it • The drawback is that much like having to work in someone else’s Emacs environment, the customizations are more complicated than the base • Very easy to experiment with new language features using Forth
Forth Overview • Forth Example Code 5 CONSTANT FLUID-LEVEL-PORT 7 CONSTANT FLUID-INPUT-VALVE 0 CONSTANT ON 1 CONSTANT OFF 63 CONSTANT FULL : WAIT-WHILE-FULL ( -- ) BEGIN FLUID-LEVEL-PORT IN FULL <> UNTIL ; : WAIT-UNTIL-FULL ( -- ) BEGIN FLUID-LEVEL-PORT IN FULL = UNTIL ; : KEEP-FULL ( -- ) BEGIN WAIT-WHILE-FULL ON FLUID-INPUT-VALVE OUT WAIT-UNTIL-FULL OFF FLUID-INPUT-VALVE OUT REPEAT ;
Forth Overview • Forth in Use • Astronomy (where it began) • Embedded systems • OpenBoot • Bitcoin script is a Forth derivative
Agenda • ShellForth in Practice • Code Generation • Forth Overview Intro • Who am I? • Forth? Seriously? • History • Basics • Key Features • Use cases • Register Usage • Compilation Modes • x64 Differences • Differences from Standard Forth
Code Generation • Register Usage and Convention (x86)
Code Generation • Compilation Mode • Forth Primitive • ESP Data Stack (except for cached top elements) • EBP Return Stack • Forth Function Call • ESP Return Stack • EBP Data Stack (except for cached top elements)
Code Generation • Inline Primitives • The Forth primitive NIP removes the second element of the stack. In Forth standard comments, this would be described as ( n1 n2 – n2 ): ; NIP movedx,ebx pop ebx
Code Generation • x64 Code Generation Differences
Code Generation • Differences from Standard Forth • Compiler Features ShellForth does not have or has changed: • Immediate/Compiled Mode • This is the ability to run Forth code as you’re compiling it; ShellForth has no interpreted mode • The ability to create defining words • Defining words are all done at the F# level • Constant definitions are changed to be entirely prefix notation • Unlike standard Forth, we don’t have a stack running while we compile • Variable definitions are changed to be variable width • Standard Forth has variables as “cell width”, and ALLOT to increase that; we just have declarations • C-style strings instead of Pascal-style (counted) strings
Code Generation • Differences from Standard Forth • Forth primitives not implemented: • Floating point • I/O • Forth compilation words • These are the things out of which new defining words are built • Forth dictionary manipulation • This includes both the ability to create new constants on the fly, or to search/modify the dictionary at runtime
Code Generation • Differences from Standard Forth • Functionality added: • Direct support for read/write to the TEB • STDCALL/STDCALLVOID words for Windows system calls • APIHASH/FINDAPICALL functionality • APIHASH is a compile-time calculation of the Metasploit hash of a function by module and name • FINDAPICALL is a built-in function that will put the address of the a function (given the hash) on the stack at runtime
Agenda • Code Generation • ShellForth in Practice • Forth Overview Intro • Register Usage • Compilation Modes • x64 Differences • Differences from Standard Forth • Who am I? • Forth? Seriously? • History • Basics • Key Features • Use cases • Demo • Taking the Demo apart • Was there ever any real point to this?
ShellForth in Practice • Demo!
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo • Looking at the Forth source code: • : SHELL_CODE • RESOLVE_FUNCTION_ADDRESSES • BEGIN • COMMAND CREATE_PROCESS • WHILE • WAIT_FOR_TERMINATION • "Not so fast..." "This isn't over yet!" MESSAGE_BOX • REPEAT • ;
ShellForth in Practice • Taking Apart the Demo • Let’s look at the implementation of CREATE_PROCESS:
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo
ShellForth in Practice • Taking Apart the Demo • Looking at the Forth source code: • VARIABLE CREATE_PROCESSA_FUNC CELLSIZE • : CREATE_PROCESSA ( create-processa-args -- retval ) • 10 CREATE_PROCESSA_FUNC @ STDCALL ; • : CREATE_PROCESS ( commandline -- errorVal ) • >R PROCESS_INFORMATION STARTUPINFO NULL NULL 0 FALSE NULL NULL R> NULL CREATE_PROCESSA ;
Wrapping Things Up • Did this ever really have a use? • Well, maybe… • The original genesis of this was “what happens when you put something that compiles to a virtual machine that most people aren’t familiar with, and wasn’t ever C or C++, in front of a reverse engineer”? • That still has some use. • Otherwise… • No, not really. But it was fun to write. • Any questions?