前言

偶然接触到了这样一个JAVA内存马,其作者也是冰蝎的作者,项目地址:

https://github.com/rebeyond/memShell

正好最近在接触JAVA,借此机会学习下大佬的代码,对自己的编程思路也有了一定的提升。当然笔者只是一个脚本小子,对代码接触不深,如果文中出现理解不当或是错误的情况,还望各位大佬不吝赐教:)

背景知识

Java Instrumentation

JAVA在SE5版本引入了Java Instrumentation,其包含在java.lang.instrument中。通过Instrumentation,我们可以构建独立于应用程序的代理端,而通过这个代理我们可以监控JVM状态以及修改类定义。而在SE6版本中,我们能够实现注入代码到运行时的JVM中。

Java Agent

前面提到的代理端也就是Java Agent,Java Agent是依附于JAVA应用程序并能对其字节码做修改的一项技术,不能独立运行。加载运行方式有两种:premain模式和attach模式,前者是在程序运行前加载,后者是在程序运行后加载,本文分析的这个木马是使用的后者。

项目作者在这篇文章中有个原理demo,感兴趣的可以看看。

分析

分析按由外及里、由简入难的顺序进行,即:用户可见功能模块、注入模块、代理模块、持久化模块。

用户可见模块分析

从项目README文件里可以看到这款木马有以下功能:

l  欢迎页

l  命令执行

l  反弹Shell

l  远程文件下载

l  文件操作

l  本地文件下载

l  文件上传

l  代理

l  菜刀连接

欢迎页

当我们获取目标服务器权限时,将木马上传至目标服务器,执行java -jar inject.jar password,即可进行进程注入获取一个隐藏进程会话。

 [+]OK.i find a jvm. [+]memeShell is injected.

此时我们去浏览器访问目标服务器即可调用目标模块。

需要注意的是,这个木马和常规木马不同。常规木马需要去访问目标木马文件来执行命令,而这款木马访问任意URL都可以调用木马执行其模块。其原理是此木马向org.apache.catalina.core.ApplicationFilterChain类的internalDoFilter方法注入了自定义代码,这个JAVA类在HTTP请求调用栈的上方,可以相应我们的任意Request请求,因此我们可以用GET请求也可以用POST请求。

internalDoFilter方法的原型如下:

换个角度来讲,这个类就是一个过滤器,而过滤器可以在客户端的请求访问后端资源之前,拦截这些请求。也可在服务器的响应发送回客户端之前,处理这些响应。也就是说用户的每一个Request请求都会经过过滤器,无论用户访问的资源是否存在,如何处理这些请求也是过滤器的核心所在。

命令执行

命令执行模块的核心就是调用Runtime.getRuntime().exec(cmd)方法来执行任意命令并获取返回结果。

例如:

反弹Shell

反弹Shell主要依靠的是Socket通信,首先判断操作系统类型,再进行Socket连接以达到反弹Shell的目的。

例如:

远程文件下载

远程文件下载支持HTTPS,下面的代码片段为了排版美观我去掉了SSL认证代码。

文件操作

文件操作包含列文件、删除文件、查看文件、删除文件夹,都是一些很基础的文件操作代码,因此我们以查看文件为例。

本地文件下载

文件上传

有普通上传方式,有Base64编码上传方式。

代理

木马里内嵌了一个reGeorg代理,因此我们可以直接使用这个木马实现代理转发,进一步渗透内网。

核心源码就是根据reGeorg改的,网上也有分析文章,此处不再多赘述。

菜刀连接

菜刀模块的源码也是根据这个JSP菜刀源码改的,但是个人觉得挺有意思——方法命名全是AA、BB、CC这种,不明白原作者是为了混淆还是只是单纯的恶作剧。

当然,以上的这些用户可见功能模块都建立在一个判断逻辑里,也就是需要正确输入我们所指定的密码。

  if (pass_the_world!=null&&pass_the_world.equals(net.rebeyond.memshell.Agent.password))

这些用户可见模块除了代理模块和菜刀模块都是一些常用的功能代码,简单易懂。紧接着我们深入分析其他模块。

注入模块分析

注入模块主要是用来遍历目标机器上的JVM实例并进行代码注入。前面提到我们有两种方式进行注入,premain和attach,这个木马里用的attach注入方式。

注入模块在运行的时候,会动态加载一个代理,也就是我们的代理模块。换句话说,代理模块会被注入模块注入到tomcat进程中。

代理模块分析

在代理端被注入到JVM后,会自动运行agentmain方法。agentmain方法在获取用户输入的参数后,会遍历获取当前所有类,如果匹配到我们要注入的目标类,则查看当前的JVM配置是否支持类的重新定义,代码如下所示。

为避免默认端口号被更改初始化失败,木马会先获取当前工程的端口号,然后对本地的tomcat发起一起请求进行初始化。进行初始化的原因原作者也解释过,因为我们在运行木马后会将木马文件删除,因此需要在删除之前没有将木马写入内存。写入内存的方式有两种:依次加载需要的类、进行一次模拟访问,这款木马选择的后者。如下代码所示,会访问一次本地的tomcat服务,以达到将木马写入内存的目的。

在注入进程后,需要删除自身,但是我注意到删除的代码还比较多,原因是操作系统的不同,删除方式也不同,例如Windows下不能直接删除一个占用中的文件。因此首先需要判断操作系统类型,如果是Linux直接删除即可。

如果是Windows,需要利用unlockFile这个方法来进行删除,unlockFile方法里使用了一个二进制文件——forceDelete.exe。例如当我们要删除代理端时,需要先用以下代码获取当前JVM进程PID。

  public static String getCurrentPid() {        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();        return runtimeMXBean.getName().split("@")[0];    }

然后利用命令执行的方式使用这个二进制文件强制删除占用的文件,并且将自身删除。

这个强制删除功能的二进制文件我们利用IDA进行简单分析,利用IDA打开后,手动调试恢复函数即可看到整个二进制文件代码逻辑。我这里就没有去恢复变量名,各位大佬凑合着看。

首先有一个判断逻辑:

  if ( !sub_411440 () || !sub_411590() )        ExitProcess(0);  

跟进sub_411440()函数,根据其代码逻辑我们发现其实就是Change_access()函数,其代码逻辑如下:

  BOOL sub_411440()    {        HANDLE v0; // eax        struct _TOKEN_PRIVILEGES NewState; // [esp+D0h] [ebp-24h]        HANDLE TokenHandle; // [esp+E8h] [ebp-Ch]            NewState.PrivilegeCount = 1;        v0 = GetCurrentProcess();        if ( !OpenProcessToken(v0, 0x28u, &TokenHandle) )            return 0;        LookupPrivilegeValueW(0, L"SeDebugPrivilege", (PLUID)NewState.Privileges);        NewState.Privileges[0].Attributes = 2;        return AdjustTokenPrivileges(TokenHandle, 0, &NewState, 0x10u, 0, 0) != 0;    }

作用是获取当前进程信息并修改其权限。

再跟进sub_411590()函数,根据其代码逻辑推断是Get_Functions_address()函数

  BOOL sub_411590()    {        v0 = GetModuleHandleW(L"ntdll.dll");        dword_41713C = (int)GetProcAddress(v0, "ZwSuspendProcess");        v1 = GetModuleHandleW(L"ntdll.dll");        QueryInformationFille = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))GetProcAddress(v1,  "ZwQueryInformationFile");        v2 = GetModuleHandleW(L"ntdll.dll");        QuerySystemInformation = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD))GetProcAddress(v2,  "ZwQuerySystemInformation");        v3 = GetModuleHandleW(L"ntdll.dll");        QueryObject = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))GetProcAddress(v3, "ZwQueryObject");        v4 = GetModuleHandleW(L"ntdll.dll");        dword_417138 = (int)GetProcAddress(v4, "ZwResumeProcess");        v5 = GetModuleHandleW(L"ntdll.dll");  14.      QueryInformationPrecess = (int (__stdcall *)(_DWORD, _DWORD, _DWORD, _DWORD, _DWORD))GetProcAddress(v5, "ZwQueryInformationProcess");        return dword_41713C && QuerySystemInformation && QueryObject && dword_417138 && QueryInformationPrecess;    }  

其作用是加载ntdll.dll模块并从中获取ZwSuspendProcess、ZwQueryInformationFile、ZwQuerySystemInformation、ZwQueryObject、ZwResumeProcess、ZwQueryInformationProcess的函数地址。

还有一个sub_411DD0()函数,根据其代码逻辑推断是Find_SubStr()函数。因此此时整个二进制文件代码逻辑就清晰了。其核心代码如下:

  if ( QueryInformationFille(TargetHandle,&v13,FileInformation,528,9) >= 0 )2.  {        if ( Find_SubStr(FileInformation + 2, L"agent.jar") )        {            v4 = GetCurrentProcess();            if ( DuplicateHandle(hSourceProcessHandle, (HANDLE)v8, v4, &TargetHandle, 0, 0, 1u) )            {                CloseHandle(TargetHandle);                ExitProcess(0);            }        }    }  

我们梳理下整个二进制文件的运行逻辑:首先打开agent.jar进程,遍历该进程的所有句柄信息,通过DuplicateHandle()函数复制句柄到本地进程,关闭文件句柄,此时就能删除占用中的文件了。

本来DuplicateHandle()函数是用来创建新句柄的,但是我们可以利用这个特性来删除被占用的文件,巧妙的实现删除文件的功能。

持久化模块分析

持久化模块主要是用于tomcat服务重启后也能继续使用这款木马,也就是说,只要目标机器不重启,tomcat服务运行起来我们无需进行二次注入也能获取权限,其核心代码如下。

主要的核心原理在于addShutdownHook钩子,JVM关闭的时候,会执行系统中已经设置的所有通过方法addShutdownHook添加的钩子,当系统执行完这些钩子后,JVM才会关闭。所以这些钩子可以在JVM关闭的时候进行内存清理、对象销毁等操作。当然这些只是一些“正规的操作”,我们可以设置一些“非法操作”,在JVM关闭的时候将我们已经注入内存的代码写入到文件,然后再调用startInject方法,startInject方法源码如下:

再次调用startInject方法后就达到了持久化的目的。

总结

我们再梳理下整个木马工作流程:

1.   获取到目标服务器权限,将Inject.jar和Agent.jar上传至服务器。

2.   执行java -jar Inject.jar password,开始注入Tomcat进程。

3.   注入模块寻找目标类。

4.   将代码注入到Tomcat进程。

5.   成功注入后删除自身。

6.   遇到Tomcat进程重启,将内存代码写入临时文件。

7.   再次注入Tomcat进程达到持久化目的。

注入的核心关键在于Servlet过滤器的internalDoFilter方法,因为所有的用户请求都会通过这个方法。

未来工作

JSP服务器的内存注入,使得JAVA内存马的通用性得到提高。原作者也提到使得这个内存马通用性提高的关键就在于要寻找到“关键类”,Tomcat里使用的是Servlet的过滤器关键类,在其他JAVA容器我们也需要找到这样的一个关键类,这也是未来工作的重点。

安洵信息技术有限公司

www.i-soon.net

以实力陪伴客户成长  使客户更加强大

400-066-5915

上海丨四川丨江苏 | 云南

dll 源码_【技术分享】 | 一个JAVA内存马的源码分析相关推荐

  1. delphi7 获取dll的类_跟我学Java内存管理----JMM精华终章(类加载器)

    1 类加载器 1.1 类的加载过程 当程序要使用某个类时,如果该类还未被加载到内存中,则系统会通过加载,连接,初始化三步来实现对这个类进行初始化. (1)加载 就是指将class文件读入内存,并为之创 ...

  2. dubbo 单元测试_技术分享——一路踩坑构建Dubbo源码

    源码环境 随着目前对技术栈的求知欲,也开始入手Dubbo源码啦!!! 构建源码第一步: 必备开发环境:Java 1.5 以上的版本:Maven 2.2.1 或者以上的版本: 官网下载源代码 官网构建文 ...

  3. 【源码及课件分享】Java实战项目之酒店客房管理系统_Java项目开发_Java项目实战

    Java实战项目又双叒叕来咯~小伙伴们请查收~酒店客房管理系统![源码及课件分享]Java实战项目之酒店客房管理系统_Java项目开发_Java项目实战_Java毕业设计https://www.bil ...

  4. 【源码及课件分享】Java实战项目之进销存管理系统_Java项目开发_Java项目实战

    还没有搞定毕设的小伙伴一定要看鸭~ Java实战项目--进销存管理系统![源码及课件分享]Java实战项目之进销存管理系统_Java项目开发_Java项目实战_Java毕业设计https://www. ...

  5. 分享一个Java生成二维码工具类

    分享一个Java生成二维码工具类 直接上代码: 1.CodeUtil.class package top.lrshuai.blog.util;import java.awt.BasicStroke; ...

  6. 分享一个JAVA专业接口开发利器,牛牛牛新鲜出炉!!!

    分享一个JAVA专业接口开发利器,集成在线接口文档 Swagger-ui,采用Jwt Token验证机制,最牛在于业务restful接口代码自动生成,更更牛的在接口可以做细化权限控制(例如:不同开发商 ...

  7. 分享一个java输出pdf的依赖包,非maven,包名:spire.pdf.jar 下载

    分享一个java输出pdf的依赖包,非maven,包名:spire.pdf.jar http://repo.e-iceblue.cn/#browse/browse:maven-public:e-ice ...

  8. IM扫码登录技术专题(三):通俗易懂,IM扫码登录功能详细原理一篇就够

    本文引用了作者"大古同学"的"二维码扫码登录是什么原理"一文的主要内容,为了更好的理解和阅读,即时通讯网收录时有修订和改动,感谢原作者的分享. 1.引言 自从微 ...

  9. Java内存马攻防实战——攻击基础篇

    ​ 在红蓝对抗中,攻击方广泛应用webshell等技术在防守方提供的服务中植入后门,防守方也发展出各种技术来应对攻击,传统的落地型webshell很容易被攻击方检测和绞杀.而内存马技术则是通过在运行的 ...

最新文章

  1. pandas数据预处理(标准化归一化、离散化/分箱/分桶、分类数据处理、时间类型数据处理、样本类别分布不均衡数据处理、数据抽样)
  2. JAVA_Thread_interrupt
  3. 机房收费系统--登录窗体
  4. C#语法:委托与方法
  5. 微软移除Visual Studio 2015中的UML
  6. 730阵列卡支持多大硬盘_华为1000多手机哪款好?推荐只此一款!华为品牌性价比最高千元机...
  7. 计算文档中不同单词出现的次数
  8. 多学一点(十三)——解决Linux kdump服务启动失败
  9. [BZOJ1007][HNOI2008]水平可见直线 计算几何
  10. ubuntu的一些技巧
  11. 51单片机学习路程(一)
  12. 管中窥豹SPDK RBD bdev 模块
  13. 西电数据挖掘实验3——复杂网络社团检测
  14. 【C语言】算法学习·逆波兰式
  15. 软件工程第五次作业——第二次结对编程
  16. python使用百度aip文字识别
  17. Linux命令之实时监控系统进程状态top
  18. Hexo-fluid主题添加51LA统计
  19. 怎样搜索计算机文档,怎么样快速搜索电脑文件 Windows系统秒搜电脑文件
  20. 北京林业大学计算机保研,北京林业大学2021年各专业保研数据详细分析

热门文章

  1. php private方法,php如何调用private方法
  2. perl转python_将行转换为perl或python中的列
  3. kali利用msf工具对ms08-067漏洞入侵靶机(win xp2)
  4. 浙江大学计算机研究生分数线初试单科学科,计算机考研|这两所自划线,单科没过线也能复试?!...
  5. 九宫格有规律高亮滚动效果
  6. css图片的全屏显示代码-css3
  7. vue命令行错误处理
  8. 几道web前端练习题目
  9. CSS position(定位)属性
  10. PAT_B_1012 数字分类 (有待改进)