P-GOhst Exploitation

(P|G)Ohst Exploitation

A primmer on utilizing the Golang (GO) programing language to rapidly prototype, and maintain the development of, post exploitation payloads by utilizing user - land loader techniques.

Abstract

This talk focuses on showcasing examples of the GO programming language being utilized to rapidly prototype, and ultimately maintain software designed to perform common or useful post-exploitation tasks. Source code for each feature will be provided, and is intended to exaggerate the limited amount of code and code familiarity required to construct relatively complex payloads capable of performing offensive security tasks fully either in an automated, or fully antonymous context.

Content

What is an “implant”?

For the purposes of the presentation of this material (as well as the duration of this document), the term “implant” will hence fourth refer to an autonomous, post – exploitation utility either in the form of "shellcode", or a standalone executable. In more layman’s terms, this means we are talking about the “cool” part of most commercially developed or publicly available exploit kit (such as Meterpreter from Metasploit, or the beacons from Cobalt Strike). These applications are meant to provide the ability to perform a host of tasks that can often include but is certainly not limited to; utilizing exploits to escalate local privileges, gathering credentials or other sensitive data from the infected device, exfiltrating data to a remote location, performing local system manipulations in order to facilitate persistent access by the attacker, or forwarding command and control (C2) directives to other devices. These actions are carried out autonomously, requiring no interaction from the attacker via the form of direct TCP socket control or non stream - based messages (such as HTTP, DNS or ICMP requests)

The current landscape

The current landscape of available implants includes a wide variety of both commercially available (usually considered illegal) and open source (usually considered legal) implementations. However, these implementations usually suffer from a variety limiting factors depending on their intended usage condition.

Open source implementations, for example, typically are well analyzed and identified by anti - virus or anti- malware systems making them difficult to utilize without some level of binary obfuscation. They are also, commonly utilized by security consultants. Whom, as users attempting to evade detection, typically utilize equally open source and or publicly available binary obfuscators to avoid detection (usually in the form of “packers” or “crypters”). This leads to the combinations of the most commonly utilized binary obfuscators and implants being targeted by anti malware systems explicitly, as well as having their communication protocols analyzed, and ultimately results in a permanently increased barrier to entry of use beyond what would typically befall any other implant technology.

Beyond this, almost all open source implant implementations are designed to facilitate real – time control and operation by the operator. This means, that performing multi end – point migrations or network wide offensive security tasks can be daunting and ultimately unaided by the implant beyond “providing a shell” to the operator on a per attack basis.

Closed source implementations however are typically built utilizing closed source, anti – reverse engineering technologies baked in, making their deployment’s cost effectiveness suffer severally due to users never truly being aware of what their implants are doing behind the scenes (i.e. perhaps the implant is back-doored by the original author). Beyond this, paying per implant is typically not a cost model that most information security professionals can work within effectively.

This organizational model also makes it nearly impossible for operators to modify or re - orient the functionality of these implants to fit more specific attack scenarios due to the “black box” nature of the software. Without this adaptability (something radially provided by almost all open source implants) operators are forced to utilize the software “as is”. As a result, many of the benefits gained from the fully antonymous design of the implants firmly within the closed source realm are often lost during the operation process simply because they are being utilized in a way they were not designed to be utilized.

The “Write your Own” alternative

Due to the afore mentioned negatives associated with using a “pre built” implant the logical conclusion for most who seek alternatives to alleviate these road blocks it to build one’s own implant. However, this process also consists of a myriad of potential setbacks. In general, constructing an implant is ultimately the same process as generic software development, safe for the specificity of targeted use outlined for the resulting software product. As a function of consequence, software development is generally considered a difficult task to accomplish entirely on one’s own accord due to all of the reasons software is typically developed by teams of people.

Platforms in the modern era of computing are numerous, and each contain their own specificities of function, as well as capability limitations and common failure points. Subsequently, writing software that is resilient and capable of operating on Microsoft Windows 10 via an x86_64 compatible desktop vs. an OSX ARM platform or a Unix compatible operating system on a MIPS mobile device is a task considered frankly daunting if not a full time job to maintain. Beyond this, the languages that compile to these platforms are not unilateral in terms of function, capability, or even operability. Some languages work on some things and don’t on others, yet writing certain features is much easier in some languages. Managing these free radicals within the modern computational landscape is usually a high enough workload to incubus an entire professional team at the very minimum; and, that is to say nothing of the anti – malware, threat endpoint detection, or human operator evasion tactics required within the software development life cycle of attack software.

In addition to these development pitfalls, implants typically implore the use of exploits or local environment manipulation tactics that are constantly in a state of change and or iteration via support from the information security community. Without the ability to implement these improvements on both a constant and consistent basis, it is assured that the operational capabilities of a given implant will fail, more than likely never again to be resurrected. Reviving outdated implant technology in lure of developing new implants around more recent technologies is an almost universally inefficient time expenditure, resulting in new techniques being implemented with less support than the software that came before it, but the old software simply being too inflexible to deploy. Finally, the development operations and general administration requirements of maintaining a C2 system are, on average, an order of magnitude more difficult to design, and deploy, when attempting to produce them for software that is intended to be covert in nature (as most implants are). Subsequently, a subtle change in a protocol due to version iteration or a small advancement in an exploit delivery mechanism can require massive overalls to the command and control structure. This repeated maintenance process can result in implant developers spending an inordinate amount of time maintaining existing implants without adding functionality as apposed to using them for their intended purpose or iterating on their capabilities.

Enter the user land loader

The user land loader is a programing technique wherein a developer implements the functionality of a standard operating system’s loader within the programing logic of an implant, allowing the implant itself to subsequently load entire compiled applications from within its own memory. Through this, we can avoid the myriad of issues documented in the previous sections by utilizing 3rd party tools in their compiled state, and by applying binary obfuscation to the components themselves as well as the resulting implant can be extremely effective against anti – malware controls, as well as exceedingly easy to deploy. In short, a user land loader and a collection of well maintained 3rd party tools combined with some mild binary obfuscation results in a vastly powerful array of utilities, autonomously packed into an easy to redeploy package, that is as anti – virus resilient as most commercially available malware.

Implementation

Depending on the target operating system, there are several library options for implementation a user land loader within arbitrary code.

Windows

On Microsoft Windows operating systems, the most readily available option is to use Memory Module . Memory Module is a native C memory encapsulated user land loader implemented as an exported function within a compile time library. While the original version of this library is not capable of passing arguments to the PE files it instantiates, a modified version exists in the form of a Git fork on my Github.com profile . At the time of this writing, the resulting pull requests have not yet been accepted upstream but by the release of this document, may in fact be included into the standard repository (so please check before attempting to utilize the forked version as there will undoubtedly be additional fixes incorporated into the most recent official version).

Linux

On Linux, there are several libraries available that implement a user land loader via a contained function call. The first and most popular of which is Libelf . While Libelf itself implements many useful functions for constructing a loader, it technically does not include a fully programed user land loader itself. However, doing so is trivial, so much so that complete implemented examples can be found at numerous locations through out the Internet. The following example, (with some code removed for brevity), is taken from the website Stack Overflow .

int main(int argc, char** argv, char** envp)
{
    int (*ptr)(int, char **, char**);
    static char buf[1048576];
    FILE* elf = fopen(argv[1], "rb");
    fread(buf, sizeof buf, 1, elf);
    ptr=image_load(buf, sizeof buf);
    return ptr(argc,argv,envp);
}

Beyond this the OSLib projects supports a single function based user land loader, but is designed to aid reverse engineering and debugging tasks. Due to this, the library is large and typically unwieldy in terms of using it in place of a simple more streamlined solution.

Additionally the android operating system implements a memory based loader (that is not entirely user land) within the Bionic framework. While Bionic is highly effective at this task, it should be noted that much of the known malware that exists for Android uses this feature and therefor is typically analyzed during the attempted discovery of implants within a live android device. Finally, since Linux is open source, modifying the existing Linux loader (the exec/execv syscall) source code to simply run in user land is a relatively simple task once past the binary parsing stage. However, binary parsing is provided by a plethora of easy to implement libraries such as Capstone or Elfio .

Apple OSX

While I am not currently aware of a self contained user land loader implementation for OSX, researcher Vincenzo Iozzo has released a Black Hat talk , and associated white paper, on his rewrite of the native OSX exec function to work in user land and entirely from memory.

Conclusion

In order to demonstrate the usefulness of the techniques previously discussed, I have released an example proof of concept entitled go-mimikatz . This example shows the ability to utilize the Go programming language to construct a binary that utilizes a user land loader (in this case , Memory Module) to deploy a 3rd party application (in this case the utility mimikatz), included at compile time, in its compiled state. The key element of the source is the line of code where the application is initiated from its place in memory as a byte slice

C.MemoryCallEntryPoint(handle)

Within this single line of code, we can implement literally every PE file in its compiled state, and deploy it within the Go memory space. This combined with the already prolific cross compiling capabilities of the language results in an immensely powerful platform from which to design antonymous implants.

References

Metadata

  • Primary Author Name: Carl Vincent (Vyrus)

  • Primary Author Affiliation: DC949

  • Primary Author Email: vyrus@dc949.org

Last updated