Exploit SLMail 5.5 Buffer overflow in the POP3 PASS parameter.
Setup
VM Setup
Kali Linux
Windows 7 x86 Ultimate
x64dbg
Immunity Debugger (In case you need mona.py for some help)
SLMail
General Instructions
Before installing SLMail 5.5 make sure you run the binary through virustotal.com and ensure that there are no malware in the distributed binary [as of 16-09-2019]. While installing make sure you accept all the defaults, as there is no dependency on the configurations as such, we just need the POP3 server up and running with all the ports opened up. After you've installed the binary, make sure you turn off the windows firewall using the command mentioned below (run as administrator), this ensures that ports are reachable from the Kali VM and there's no filtering.
C:\> NetShAdvfirewallsetallprofilesstateoff
After setting all these up, run a port scan from the Kali to ensure port 110 is reachable and the machine is reachable as well.
$nmap-p110192.168.219.128StartingNmap7.80 ( https://nmap.org ) at 2019-09-16 19:13 ISTNmapscanreportfor192.168.219.128Hostisup (0.00061s latency).PORTSTATESERVICE110/tcpclosedpop3Nmapdone:1IPaddress (1 hostup) scanned in 0.07 seconds
While debugging and exploit development ensure that POP3 server is running fine. The status of the server can be checked from the SLmail Configuration application's control tab menu.
SLmail Configuration Control Menu
Finding the EIP Offset
We'll attach the x64dbg to the SLmail process and use the following python script to send out payload to the application from Kali machine
Attached process (Paused state)
Before sending anything to the server make sure, after attaching the process, you've change the process state to running (F9).
We'll be using the following code snippet to overflow the EIP with A's. I started from 1000 and kept increasing till 3000, at which point I got the EIP overflow.
EIP is overwritten with a bunch of A's
Now we'll try and find the exact offset value for our EIP.
EIP value with the cyclic pattern
And to get the offset value we'll run the following, and it turns out our EIP is after 2606 characters.
Shell-code location identification
Now we'll see if we can get a place to put our shell-code in our payload, for this we'll try to find in the dump if we get A's or C's in any of the registers and we'll use the following script to check that.
To our good luck, we can see that ESP points to the starting of the C's in our payload, we'll this is just awesome. Now we have to find the instruction JMP ESP and replace 0xCCCCCCCC with it's address and we'll be able to jump to our shell-code area. We'll take help from x64db and try to find JMP ESP in all the modules. In the CPU section we'll right click, Search For > All Modules > Command, and type in JMP ESP and wait for our results in the references tab. We found 1576 results, you can use any of these, make sure the one you are using does not have any bad character, in this case, it would be any string terminating character (Newline (0xA), Return Carriage (0xD), or Null Byte (0x00)) and you can also use mona.py to ensure that there is no ASLR, or re-base.
Shell-code generation
We'll use msfvenom to generate our shell-code, encode it with Shikata ga-nai encoder and avoid all the string terminating bad characters.
For reverse shell tcp, we need to keep a listening on the port for incoming connections which can be done using netcat.
Final payload generation
Our final payload script looks something like this with the shell-code, JMP ESP instruction, and other fillers.
You might notice that we've added a NOP sled before the shell-code, this is put in place to ensure that if there's some misalignment with the EIP and the shell-code, it does not affect the shell-code execution.
After executing the final payload script we have the shell as evident in the screenshot below.
And as the application was running with elevated privileges, we have NT Authority/SYSTEM access.