dll 源碼_【技術分享】 | 一個JAVA內存馬的源碼分析

前言

偶然接觸到了這樣一個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.

此時我們去瀏覽器訪問目標服務器即可調用目標模塊。

4449d72823b2cbbe68d6e254a6813ceb.png

需要注意的是,這個木馬和常規木馬不同。常規木馬需要去訪問目標木馬文件來執行命令,而這款木馬訪問任意URL都可以調用木馬執行其模塊。其原理是此木馬向org.apache.catalina.core.ApplicationFilterChain類的internalDoFilter方法注入了自定義代碼,這個JAVA類在HTTP請求調用棧的上方,可以相應我們的任意Request請求,因此我們可以用GET請求也可以用POST請求。

internalDoFilter方法的原型如下:

b10f6954f5f8956d4075eaa5364b60dd.png

換個角度來講,這個類就是一個過濾器,而過濾器可以在客戶端的請求訪問后端資源之前,攔截這些請求。也可在服務器的響應發送回客戶端之前,處理這些響應。也就是說用戶的每一個Request請求都會經過過濾器,無論用戶訪問的資源是否存在,如何處理這些請求也是過濾器的核心所在。

命令執行

命令執行模塊的核心就是調用Runtime.getRuntime().exec(cmd)方法來執行任意命令并獲取返回結果。

f8c997298966e5e050b04c8cebc4cdc2.png

例如:

5ee8b5a4c5ed965de96cc3faaf5865b7.png

反彈Shell

反彈Shell主要依靠的是Socket通信,首先判斷操作系統類型,再進行Socket連接以達到反彈Shell的目的。

85250438efc62dd264e45d4bc56d4c3b.png

例如:

ea259d07b0aa869ea876394e2791c155.png

遠程文件下載

遠程文件下載支持HTTPS,下面的代碼片段為了排版美觀我去掉了SSL認證代碼。

ed2bfaa2a2b0f5d3af1c748fe6f7a926.png

文件操作

文件操作包含列文件、刪除文件、查看文件、刪除文件夾,都是一些很基礎的文件操作代碼,因此我們以查看文件為例。

4faa4136bc43e88871e8b4c2169b1e60.png

b2c22fe632a52879f46cfe3c18775211.png

本地文件下載

f3907c18a02bba323771e446044fe19d.png

文件上傳

有普通上傳方式,有Base64編碼上傳方式。

09d8141eaf76fe319c74a2e234ca8ac8.png

代理

木馬里內嵌了一個reGeorg代理,因此我們可以直接使用這個木馬實現代理轉發,進一步滲透內網。

94e1f8fd132e5e0fac1dbbb572d2481d.png

核心源碼就是根據reGeorg改的,網上也有分析文章,此處不再多贅述。

菜刀連接

菜刀模塊的源碼也是根據這個JSP菜刀源碼改的,但是個人覺得挺有意思——方法命名全是AA、BB、CC這種,不明白原作者是為了混淆還是只是單純的惡作劇。

e2e9cfbf4b124a79d163ca53723988ab.png

當然,以上的這些用戶可見功能模塊都建立在一個判斷邏輯里,也就是需要正確輸入我們所指定的密碼。

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

這些用戶可見模塊除了代理模塊和菜刀模塊都是一些常用的功能代碼,簡單易懂。緊接著我們深入分析其他模塊。

注入模塊分析

注入模塊主要是用來遍歷目標機器上的JVM實例并進行代碼注入。前面提到我們有兩種方式進行注入,premain和attach,這個木馬里用的attach注入方式。

注入模塊在運行的時候,會動態加載一個代理,也就是我們的代理模塊。換句話說,代理模塊會被注入模塊注入到tomcat進程中。

71a56404abae545a7fed92c2762286e6.png

代理模塊分析

在代理端被注入到JVM后,會自動運行agentmain方法。agentmain方法在獲取用戶輸入的參數后,會遍歷獲取當前所有類,如果匹配到我們要注入的目標類,則查看當前的JVM配置是否支持類的重新定義,代碼如下所示。

1eb341d52d51b1c093f7c38047c0a2ed.png

為避免默認端口號被更改初始化失敗,木馬會先獲取當前工程的端口號,然后對本地的tomcat發起一起請求進行初始化。進行初始化的原因原作者也解釋過,因為我們在運行木馬后會將木馬文件刪除,因此需要在刪除之前沒有將木馬寫入內存。寫入內存的方式有兩種:依次加載需要的類、進行一次模擬訪問,這款木馬選擇的后者。如下代碼所示,會訪問一次本地的tomcat服務,以達到將木馬寫入內存的目的。

f869cb6b5c55019ab9f801387b232127.png

在注入進程后,需要刪除自身,但是我注意到刪除的代碼還比較多,原因是操作系統的不同,刪除方式也不同,例如Windows下不能直接刪除一個占用中的文件。因此首先需要判斷操作系統類型,如果是Linux直接刪除即可。

6b8ea3ba819fae8a9c01c81442f67d3a.png

如果是Windows,需要利用unlockFile這個方法來進行刪除,unlockFile方法里使用了一個二進制文件——forceDelete.exe。例如當我們要刪除代理端時,需要先用以下代碼獲取當前JVM進程PID。

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

然后利用命令執行的方式使用這個二進制文件強制刪除占用的文件,并且將自身刪除。

27bc229ab78770b7e70b5b2487588769.png

這個強制刪除功能的二進制文件我們利用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服務運行起來我們無需進行二次注入也能獲取權限,其核心代碼如下。

2c1735ecdf8226076c1811cef804eef9.png

主要的核心原理在于addShutdownHook鉤子,JVM關閉的時候,會執行系統中已經設置的所有通過方法addShutdownHook添加的鉤子,當系統執行完這些鉤子后,JVM才會關閉。所以這些鉤子可以在JVM關閉的時候進行內存清理、對象銷毀等操作。當然這些只是一些“正規的操作”,我們可以設置一些“非法操作”,在JVM關閉的時候將我們已經注入內存的代碼寫入到文件,然后再調用startInject方法,startInject方法源碼如下:

c081c4925c3e705d3842c87207aeece3.png

再次調用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容器我們也需要找到這樣的一個關鍵類,這也是未來工作的重點。

7101c464fb8835b1c16bff73614263f3.png

安洵信息技術有限公司

www.i-soon.net

f398d08c7cb79bac86ad582a1dc5fdd2.png

以實力陪伴客戶成長??使客戶更加強大

400-066-5915

上海丨四川丨江蘇 | 云南

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/374471.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/374471.shtml
英文地址,請注明出處:http://en.pswp.cn/news/374471.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ThunderSearch(閃電搜索器)_網絡空間搜索引擎工具_信息收集

文章目錄 ThunderSearch簡介1 項目地址2 使用方式2.1 配置文件config.json說明2.2 構建和運行 3 使用式例 ThunderSearch簡介 ThunderSearch(閃電搜索器)是一款使用多個(【支持Fofa、Shodan、Hunter、Zoomeye、360Quake網絡空間搜索引擎】網絡空間搜索引…

字符串匹配方法

介紹兩種字符串匹配方法1.暴力匹配母串用s表示,長度為m子串用p表示,長度為n時間復雜度為:(m-n1)n算法:從s串的第一個字符開始匹配,若匹配,繼續根據p向后匹配,若后續的不匹配,s右移重新匹配p 2.K…

區分幾進制的標志

自己總是記不住進制的開頭標記,就寫下來忘了就看看 1.二進制:Binary,數字以0b 、0B開頭 2.八進制:octal number system,數字自然以0打頭 3.十六進制:hexadecimal,以0x、0X開頭

每個人都知道MVC…

從一個最近的博客中,您可能已經了解到我最近一直在進行一些采訪,因為他們是針對Web應用程序開發人員的,所以我問的一個問題是“您能解釋一下MVC模式是什么嗎?”,值得稱贊的是,每個候選人知道答案。 對于不認…

php無限分類

無限循環 1.需要套2個foreach 2.2個foreach結構一樣 純代碼獲取數據 public function CycleData($parent_id0){$where[parent_id] $parent_id;$res $this->m->where($where)->field(id,name)->select();foreach($res as $k>$v){$result[$v[id]][id] $v[id];$r…

動態網頁數據的采集方案

我在上一篇文章中介紹了使用ScrapySharp快速從網頁中采集數據,這種方式是通過直接發送的Http請求來獲取的原始頁面信息,對于靜態網頁非常有效,但還有許多網站中的頁面內容并非全部存放在原始的頁面中,很多內容是通過javascript來動…

r語言ggplot2 多線圖繪制圖例_plotnine: Python版的ggplot2作圖庫

騰訊課堂 | Python網絡爬蟲與文本數據分析同樣的基本作圖任務,plotnine比matplotlib和seaborn代碼量少,更美觀。所以我又重新發一遍,大家可以先收藏起來,后面總有用到的時候~R語言的ggplot2繪圖能力超強,python雖有mat…

單元和集成測試的代碼覆蓋率

我最近在一個寵物項目中著手構建自動化的UI(集成)測試以及普通的單元測試。 我想將所有這些集成到我的Maven構建中,并提供代碼覆蓋率報告,以便我可以了解測試覆蓋率不足的區域。 我不僅發布了項目的源代碼,還整理了一個…

javascript事件與event對象的屬性

javascript事件列表解說事件瀏覽器支持解說一般事件onclickIE3、N2鼠標點擊時觸發此事件ondblclickIE4、N4鼠標雙擊時觸發此事件onmousedownIE4、N4按下鼠標時觸發此事件onmouseupIE4、N4鼠標按下后松開鼠標時觸發此事件onmouseoverIE3、N2當鼠標移動到某對象范圍的上方時觸發此…

感想

讀完三篇文章看到了前輩們的努力與堅持和對各自的學科的熱愛,以及各位前輩的奮斗的艱苦環境,我與那些前輩相比也許還達不到前輩們的那種級別,但是我的學習的條件卻比那些前輩們好的多,看完前輩們的奮斗史,以及前輩們的…

python學生分布_Python數據分析實戰之分布分析

前言 本文的文字及圖片來源于網絡,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理。 作者:嚴小樣兒 分布分析法,一般是根據分析目的,將數據進行分組,研究各組別分布規律的一種分析方法。…

使用Spring Security 3.1保護RESTful Web服務,第3部分

1.概述 本教程顯示了如何使用Spring和基于Java的Spring Security 3.1來保護REST服務 。 本文將重點介紹如何使用“登錄和Cookie”方法專門針對REST API設置安全配置。 2. Spring Security的體系結構完全基于Servlet過濾器,因此,在HTTP請求處理方面&…

一次完整的HTTP請求所經歷的7個步驟

HTTP通信機制是在一次完整的HTTP通信過程中,Web瀏覽器與Web服務器之間將完成下列7個步驟: 1、建立TCP連接 在HTTP工作開始之前,Web瀏覽器首先要通過網絡與Web服務器建立連接,該連接是通過TCP來完成的,該協議與IP協議共…

jQuery基礎--樣式篇(3)

1.jQuiery對象與DOM對象   對于剛剛接觸jQuery的初學者,我們要清楚認識一點:jQuery對象與DOM對象是不一樣的。可能一時半會分不清楚哪些是jQuery對象,哪些是DOM對象,下面重點介紹一下jQuery對象,以及兩者相互間的轉換…

hls fifo_HLS優化方法DATAFLOW你用了嗎

上期內容:異步跨時鐘域電路該怎么約束DATAFLOW作為HLS的一種優化方法,對于改善吞吐率(Throughput)、降低延遲(Latency)非常有效。DATAFLOW的作用對象DATAFLOW可以作用于函數,也可以作用于for循環。如下圖所示(圖片來源Figure62, Figure 63, u…

Java 8虛擬擴展方法

我一直關注Java 8 Lambda表達式項目的發展已經有一段時間了,我對其當前的進展狀態感到非常興奮。 我發現的最新“易于理解”的演示文稿是這樣的: http://blogs.oracle.com/briangoetz/resource/devoxx-lang-lib-vm-co-evol.pdf 現在,作為一名…

python爬蟲 庫_七款必備的Python爬蟲庫,你知道幾個?

很多你需要的信息數據都是在網站內,雖然有些網站的數據會以整潔、結構化的形式呈現,但大部分網站卻無法做到這樣。因此,當你想要獲得一些數據的時候,你需要一些爬蟲工具幫助抓取,然后再對其進行分析。今天,…

62個Android Studio小技巧合集

轉載: 原文鏈接:http://laobie.github.io/android/2016/02/14/android-studio-tips.html轉載于:https://www.cnblogs.com/kesteler/p/5618490.html

在Hibernate,EhCache,Quartz,DBCP和Spring中啟用JMX

繼續使用JMX的過程(請參閱: 人類JMX ),我們將學習如何在一些流行的框架中啟用JMX支持(通常是統計和監視功能)。 這些信息大部分都可以在項目的主頁上找到,但是我決定在收集這些信息的同時&#…

二叉樹遍歷(前中后)

二叉樹前序遍歷&#xff1a; /*** Definition for binary tree* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode(int x) : val(x), left(NULL), right(NULL) {}* };*/ class Solution { public:vector<int> preorderTravers…