Home-Grown Red Team: Let’s Evade AV And Run Lazagne
UPDATE: There was a scaredy-cat that posted a comment on this story then immediately deleted it. The comment read “This is really terrible! Absolutely will not work!”
Typically, I would ignore this, but it kind of irked me because the article shows that it in fact did work. If you install a clean version of Windows Server 2016 and do not update it, it will probably still work. Same for a clean version of Windows 10. It might even work on Microsoft’s trial Windows 11 VM.
In the article, I submit the signature of the malware to VirusTotal. They have undoubtedly reported this to Microsoft and other vendors so will it work now, months after publishing? No, probably not. This is just an example of how string replacement can shift the malware signatures enough to get past Defender.
I’m sure there are other articles that I have written on here that are outdated. Maybe one day I’ll revisit them. Maybe not. Take the articles as references and go experiment with. Do the work yourself. “This is really terrible! Absolutely will not work!” is not a constructive comment and doesn’t help junior red teamers. This isn’t OffSec. Take that angry energy back to the PWK forums or infosec Twitter cool guy.
What is Lazagne?
As red teamers know, having a way to dump passwords is essential to operations. Although there are many methods of dumping passwords, one of the most unique is to use the Lazagne project.
Lazagne is a great red teaming tool because of the sheer volume of passwords it can dump. At the time of writing this article, lazagne has the ability to dump passwords for various operating systems, browsers and applications. Some of these include Windows Credential Manager, FileZilla, Skype, Firefox, Google Chrome, Microsoft Edge and Outlook.
Lazagne also has the ability to drop password hashes from LSASS, but you need admin privileges to do that. All of the other modules can be run from a low privileged user, including the Windows Credential Manager. This is exciting for a red teamer because if you can get one password, more than likely, that password will be used in another system, application or database.
The problem is that Lazagne is (and has been for a while) caught by various AV engines.
Uploading the Lazagne.exe file to Virus Total, we see that the application is flagged by 47 out of the 69 AV vendors.
One of these engines is Windows Defender. Let’s see if we can change Lazagne’s signatures enough to get past defender and other AV vendors.
Let’s get started!
What You’ll Need
- Linux VM (I’ll use Ubuntu)
- Windows 10 VM with Python installed
Downloading Lazagne
There are pre-compiled EXEs available, but those will get flagged by Defender, so we’re going to have to compile our custom malware from source. We’ll start out by downloading the source code from the Lazagne github page. The current latest version is 2.4.3.
Download the “Source Code (zip)” file from the page to your Linux VM. It should be the 3rd one down under 2.4.3.
You should now have a “Lazagne-2.4.3.zip” file in your downloads folder. I like to move it to my desktop to extract. Double click the zip file and then click “Extract.”
Choose the extraction folder. I like to keep it on my desktop. Now you should have a Lazagne-2.4.3 folder. Next, we’re going to open a terminal and cd into the Lazagne directory.
CD into the “Windows” directory. You should see 3 files in the directory.
Now we are ready to start evading AV with our executable.
NOTE: These steps are only for the Windows executable, but could be replicated for the Mac and Linux versions of Lazagne also.
How Are We Going To Evade AV With This?
The simple answer? String replacement. Defender and other AV engines scan scripts, binaries and other files looking for known signatures of malware. But if we switch those known signatures out for other values, we can get past some of them. This is an easy trick (and extremely common) but it still works!
Once inside the Windows directory of Lazagne, we’re going to use a simple, recursive find and replace one-liner in bash.
This one-liner will change all instances of the word “lazagne” to “ziti” recursively. That means it will change all instances of it in the files of the Windows directory and every subdirectory.
find -type f -exec sed -i ‘s/lazagne/ziti/g’ {} +
So now if we cat out lazagne.py we see that it’s calling for a config file named “ziti.”
Notice that after the one-liner, the Python file is still known as “laZagne.py.” This is because the one-liner does not change file names, only strings. We’ll have to get rid of that also, but that will come later.
Searching through the laZagne.py file, we find another signature.
There is another function call for “runLaZagne.” We need to switch this one out too. Let’s go back to our terminal and run the same one-liner with different parameters to replace those strings.
But wait! Notice that there are 2 versions of this string. The first one highlighted above is “LaZagne” and the other is “laZagne.” This is important.
Let’s start with the first instance. We’ll switch out “LaZagne” with “ZiTi.” Here’s our one-liner.
find -type f -exec sed -i ‘s/LaZagne/ZiTi/g’ {} +
If I reload the text editor, I see that the text has now changed to our new string.
Now, we need to replace the second one. But if you notice, the text, “laZagne” is also the name of our python file “laZagne.py.”
The specific call in this text is for the help function of the python script. Let’s go back to our terminal and run our one-liner one more time to switch “laZagne” out with “ziTi”.
find -type f -exec sed -i ‘s/laZagne/ziTi/g’ {} +
I reload the text editor and now our new string is in there.
Okay! Now let’s get rid of some of these comments. Comments are a big part of binary signatures so getting rid of them is very important. We’ll delete the comments around “By Alessandro ZANNI” so the top of the new python file should look like this.
You can go through the rest of the python files and delete the comments or switch them out for whatever values you want. I won’t go in depth with that since it’s pretty straight forward.
Now, let’s change our “laZagne.py” filename to “ziTi.py” to match the function calls. We’ll also change the “lazagne” directory name to “ziti” to match our function calls and “lazagne.spec” to “ziti.spec.”
The directory contents should now look like this.
Let’s Compile Our Malware
Now we need to transfer our Lazagne directory over to the Windows instance. With the folder transferred, we can cd into it within a powershell session.
Install the requirements through pip.
pip install -r requirements.txt
The requirements should install pyinstaller. You will need this to compile the binary. If you don’t have pyinstaller installed, you can install it with the command below.
pip install pyinstaller
Now that we have all of our requirements installed, we can compile.
pyinstaller — onefile ziTi.py
And if all goes well, you should see an EXE confirmation.
The binary is compiled to the “dist” directory within the “Windows” folder. Let’s cd over there and see if we have a binary.
All right, if everything compiled correctly, we should be able to run the binary and get the help prompt.
That’s a good sign! Let’s test it against my machine and see if we can get any passwords.
Uh oh! Wendy! Get a better password!
The Windows Credential Manager module is working! But the big test is whether or not Defender will catch it. Let’s scan it and see. I’m going to transfer this to a fully patched instance of Windows 10.
All right! We’ve got some AV resistant malware (when it comes to Defender). But what about other engines?
Yep, we’re going to upload to VirusTotal to see how many engines can still detect us.
Okay, 11 out of 69 isn’t FUD, but clearly on our way. Not too bad for just replacing 3 strings and getting rid of one comment. In fact, only one AV vendor recognized it as Lazagne.
Most importantly, this version of Lazagne can get past Windows Defender. There’s more that you can do to get it past more AV vendors, but Lazagne is very well known so major modifications to the functionality of the program would be needed to break behavioral heuristic signatures.
One way to go deeper into string replacement to evade the signature would be to change the module names. When you do this you will probably get errors because you’ll have to change the names in other files such as module_manager.py in the “build” directory.
With a little time and effort, you can easily evade more vendors with this approach. I’ve created a script on my github to automate this entire process.
Until next time, you can follow me here on Medium or on twitter @assume_breach
I’ve created a github repo for my HomeGrown Red Team series. Check it out for more tools, BashBunny payloads and more!