Oct 29, 2018 12:12 PM
(This post was last modified: Oct 29, 2018 02:37 PM by Goodies.)
TL;DR: CShell Github Link
I'm just releasing this project that I had worked on about a year ago when I was interested in writing more complex shellcode payloads, but I was pretty much hitting the ceiling of my assembly language capabilities. For this reason, I thought it would be much easier to just simply write my payloads in something sane and readable like C. However, C compilers will create a binary file from object code that is complete with storage sections and symbols, but our shellcode payload should generally just contain executable instructions and nothing more.
When I was writing a fully positionally independent shellcode payload for Windows, I really enjoyed this article which essentially describes how to utilize C-compiled binaries to extract its own executable section. Utilizing customized shellcode should be in every hacker's repertoire, but it can definitely be tedious to learn, and especially difficult to master. Because Windows doesn't work on system calls, it parses the export table of standard libraries (that are consistently loaded into the same address space for various reasons) and uses them just like normal kernel functions. Linux, however, doesn't quite work the same way. Instead, it uses so-called "system calls" that each perform a specific function and are implemented by the kernel.
There are a few things to watch out for when writing positionally-independent C code:
CShell Syscall Wrapper
There are two syscall wrappers that come packaged in with CShell: x86 and x64. These are for i386 and amd64 platforms respectively. These are the ONLY assembly portions of the entire project. Any other platforms that wish to be supported must provide a similar system-specific syscall wrapper. This wrapper is meant to accept a syscall number and up to 6 additional parameters (for x86 and x64 this is sufficient). In the nomenclature I have used (cshell1, cshell2, cshell[N]...) N determines the number of parameters.
32 Bit Assembly Syscall Wrapper
64 Bit Assembly Syscall Wrapper
Syscall Headers
Each (supported) syscall is nothing more than a preprocessor definition to call the desired `cshell[N]` function (where N is the number of parameters) which also converts the provided arguments to a uniform type (unsigned long). There are so many syscalls that I haven't even looked at, but you can always call the cshell functions directly.
Header Wrapper (Click to View)
Writing a Payload
Writing the payload is similar to how you would go about writing a normal C program, but instead of using nice, portable, standard library functions, you must use system calls and implement your own versions of various functions. You are responsible for memory allocation, child process management, string parsing, etc... This really isn't so bad! I wrote a client that:
Here's the source. (Click to View)
Once you compile it with the assembly shellcode wrapper that correctly suits your architecture (Makefile provided), the resulting binary will be a static executable ELF file. Using the provided `gettext.txt` shell script, or performing this manually, you can use the `objdump` to identify the starting and ending positions of the `.text` (executable) section of the binary. Simply extract that portion of the binary, and we have our executable shellcode!
The resulting payload isn't really tiny... it's just about 2KB (although most of it goes to implementing the tiny FTP client, so a raw TCP file transfer would't be nearly as big to implement). But it is shellcode, and it is full positionally independent. This can be injected into an arbitrary process, or used as-is to poison an ELF file, or be triggered from any number of attack vectors in the heap/stack. It relies on absolutely no knowledge of library locations or anything external.
As of right now it definitely works with the FTP server I tested with, but it wouldn't work on an unauthenticated FTP server. It isn't a fully features FTP client; that would be too bloated even for this monstrosity. Instead, it just implements exactly what is needed to connect to that server. The resulting file is saved in /tmp/, but could be easily tailored to save somewhere else. This could be an incredibly simple bootstrap to deploy a much more sophisticated bootstrap.
I'm just releasing this project that I had worked on about a year ago when I was interested in writing more complex shellcode payloads, but I was pretty much hitting the ceiling of my assembly language capabilities. For this reason, I thought it would be much easier to just simply write my payloads in something sane and readable like C. However, C compilers will create a binary file from object code that is complete with storage sections and symbols, but our shellcode payload should generally just contain executable instructions and nothing more.
When I was writing a fully positionally independent shellcode payload for Windows, I really enjoyed this article which essentially describes how to utilize C-compiled binaries to extract its own executable section. Utilizing customized shellcode should be in every hacker's repertoire, but it can definitely be tedious to learn, and especially difficult to master. Because Windows doesn't work on system calls, it parses the export table of standard libraries (that are consistently loaded into the same address space for various reasons) and uses them just like normal kernel functions. Linux, however, doesn't quite work the same way. Instead, it uses so-called "system calls" that each perform a specific function and are implemented by the kernel.
There are a few things to watch out for when writing positionally-independent C code:
- No use of any functions in the standard library. This can definitely seem tedious, but it doesn't really take that long getting used to. Note: you CAN still use any type/struct/enum definition or PP macro that you wish.
- Don't use string literals in function calls or in pointer assignments. This is just a feature of C compilers; they will place string literals in a separate section of the resulting binary. In order to prevent this, declare strings as arrays instead as this will store the characters on the stack.
- NEVER use `goto`. EVER. Except in this case.
CShell Syscall Wrapper
There are two syscall wrappers that come packaged in with CShell: x86 and x64. These are for i386 and amd64 platforms respectively. These are the ONLY assembly portions of the entire project. Any other platforms that wish to be supported must provide a similar system-specific syscall wrapper. This wrapper is meant to accept a syscall number and up to 6 additional parameters (for x86 and x64 this is sufficient). In the nomenclature I have used (cshell1, cshell2, cshell[N]...) N determines the number of parameters.
32 Bit Assembly Syscall Wrapper
PHP Code
<?php
.intel_syntax noprefix
.text
.globl cshell1, cshell2, cshell3, cshell4, cshell5, cshell6
cshell1:
cshell2:
cshell3:
cshell4:
cshell5:
cshell6:
//; create a stack frame to preserve previous base pointer
push ebp
mov ebp, esp
//; move all possible arguments into gp registers
mov eax, [ebp+0x08]
mov ebx, [ebp+0x0c]
mov ecx, [ebp+0x10]
mov edx, [ebp+0x14]
mov esi, [ebp+0x18]
mov edi, [ebp+0x1c]
//; save current ebp
push ebp
mov ebp, [ebp+0x20]
//; kernel int
int 0x80
//; restore ebp and destroy the stack frame
pop ebp
mov esp, ebp
pop ebp
ret
64 Bit Assembly Syscall Wrapper
PHP Code
<?php
.intel_syntax noprefix
.text
.globl cshell1, cshell2, cshell3, cshell4, cshell5, cshell6
cshell1:
cshell2:
cshell3:
cshell4:
cshell5:
cshell6:
//; create a stack frame
push rbp
mov rbp, rsp
//; move all parameters to set up a syscall
mov rax, rdi
mov rdi, rsi
mov rsi, rdx
mov rdx, rcx
mov r10, r8
mov r8, r9
mov r9, [rbp + 0x10]
//; execute the syscall
syscall
//; destroy the stack frame
mov rsp, rbp
pop rbp
ret
Syscall Headers
Each (supported) syscall is nothing more than a preprocessor definition to call the desired `cshell[N]` function (where N is the number of parameters) which also converts the provided arguments to a uniform type (unsigned long). There are so many syscalls that I haven't even looked at, but you can always call the cshell functions directly.
Header Wrapper (Click to View)
Writing a Payload
Writing the payload is similar to how you would go about writing a normal C program, but instead of using nice, portable, standard library functions, you must use system calls and implement your own versions of various functions. You are responsible for memory allocation, child process management, string parsing, etc... This really isn't so bad! I wrote a client that:
- Forks child processes that perform the following:
- Spawns a reverse TCP shell using the typical dup2/execve over a TCP socket method.
- Connects to a public FTP server with a username and password and downloads the remote file `readme.txt` to the local file `/tmp/testing.txt`
Here's the source. (Click to View)
Once you compile it with the assembly shellcode wrapper that correctly suits your architecture (Makefile provided), the resulting binary will be a static executable ELF file. Using the provided `gettext.txt` shell script, or performing this manually, you can use the `objdump` to identify the starting and ending positions of the `.text` (executable) section of the binary. Simply extract that portion of the binary, and we have our executable shellcode!
The resulting payload isn't really tiny... it's just about 2KB (although most of it goes to implementing the tiny FTP client, so a raw TCP file transfer would't be nearly as big to implement). But it is shellcode, and it is full positionally independent. This can be injected into an arbitrary process, or used as-is to poison an ELF file, or be triggered from any number of attack vectors in the heap/stack. It relies on absolutely no knowledge of library locations or anything external.
As of right now it definitely works with the FTP server I tested with, but it wouldn't work on an unauthenticated FTP server. It isn't a fully features FTP client; that would be too bloated even for this monstrosity. Instead, it just implements exactly what is needed to connect to that server. The resulting file is saved in /tmp/, but could be easily tailored to save somewhere else. This could be an incredibly simple bootstrap to deploy a much more sophisticated bootstrap.
SRPP Discord Server
I am a professional network/cloud security architect.
My Old Tutorials
I am a professional network/cloud security architect.
My Old Tutorials



