程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> APM軟件原理分析,apm原理分析

APM軟件原理分析,apm原理分析

編輯:關於C語言

APM軟件原理分析,apm原理分析


目錄

APM軟件原理分析    1

0x00 背景    1

0x01 安裝過程    1

0x02 啟動過程    5

0x03 觸發過程    7

0x04 整體流程    13

0x05 資源    13

 

 

APM軟件原理分析

0x00 背景

本次使用PHP網站的APM監控插件作為研究對象,目的在於搞清:

1)分析安裝過程中對哪些進程和文件進行了修改;

2)插件啟動過程中對哪些進程進行了修改,調用了哪些函數;

3)程序運行過程中,如何觸發監控,相關進程之間的數據傳遞;

4)得到監聽插件對mysql,apache的hook點;

 

相關工具:IDA,gdb,strace,tcpdump,ps,lsof

相關知識:PHP擴展原理,PHP基本運行原理,socket進程間通信

環境:kail linux + apache2 + mysql + php5

Tips:APM 全稱Application Performance Management & Monitoring,應用性能管理 & 監控。用來監控和管理應用軟件是否有效運行的。主要指對企業的關鍵業務應用進行監測、優化,提高企業應用的可靠性和質量,保證用戶得到良好的服務,降低IT總擁有成本(TCO)。

0x01 安裝過程

百度搜索了一個APM軟件作為研究對象。

1. 用strace 跟蹤安裝過程,分析安裝軟件對哪些文件做了修改

用ps命令找到安裝文件的PID為7096

然後用strace –p 7096 –o log.txt(-p指定進程PID,-o指定輸出結果保存目錄)

安裝過程中會需要填寫licensekey,php安裝路徑等。

 

2. strace結果分析

安裝程序修改了php.ini

將安裝包中的so文件拷貝到php的擴展庫路徑下

將守護文件拷貝到/usr/bin/目錄下

將安裝過程寫入log日志中

找到日志文件可以直接對安裝過程進行分析,不過跟strace中找到的結果類似

還對php5的cli和apache2的conf.d進行了修改。

 

Php.ini

 

3. 安裝過程分析

安裝程序找到

這個過程中可以找到擴展oneapm.so,守護進程oneapm-daemon,可以丟到IDA中去分析了。

 

Tips: php擴展

有些頻繁使用的函數如果使用php語言編寫效率很低,如果采用php擴展,即用C語言編寫函數,然後編譯成so文件,修改php.ini文件,即可調用該函數。通過這種調用C語言庫函數的方式可以極大的提升函數效率。

參考:http://www.open-open.com/lib/view/open1392188698114.html

0x02 啟動過程

在oneapm.so文件中,有get_module入口,該函數通過獲取PC值,然後加一定的偏移,進入到apm_module_entry_ptr模塊入口。

在apm_module_entry_ptr中是一張函數表,包含了一下幾個函數

其中activate相關函數是激活模塊,發生在請求階段,需要觸發一定的條件才會執行,其他幾個函數在程序啟動時,初始化階段執行。

Tips:PHP運行原理

開始階段

PHP的整一個開始階段會經歷模塊初始化和模塊激活兩個階段。

MINIT 即模塊初始化階段,發生在Apache/Nginx啟動以後的整個生命周期或者命令行程序整個執行過程中,此階段只進行一次

RINIT模塊激活,發生在請求階段。

參考:http://www.mamicode.com/info-detail-1028100.html

 

Apache2 啟動時會自動調用其他幾個函數,因為php.ini中引入了oneapm.so,這幾個函數是在模塊初始化階段被執行的。通過ps與cat /proc/{PID}/maps可以看到apache對oneapm.so進行了引用。

 

zm_startup_apm

zm_startup_apm會fork()進程,然後去啟動oneapm-daemon守護進程。所以軟件安裝完成後,需要重啟apache。其余的則是做一些初始化工作。

 

 

zm_info_apm

zm_info_apm則是收集一些基礎信息。

 

整個啟動階段,apache2 加載oneapm.so,對模塊進行初始化,自動調用以上幾個函數,啟動守護進程oneapm-daemon,收集一些基本函數。

0x03 觸發過程

用tcpdump抓包,可以看到服務器向展示網站傳輸性能信息。

1.監控oneapm-daemon守護進程獲取數據交互線索

用strace對oneapm-daemon進程進行監控。

Strace –ff –p 1278 –s 1024 –o oneapm (-ff監控子進程子線程,與-o配合使用將結果寫到不同的文件中, -s指定一行的長度, -p指定進程PID)

oneapm-daemon會啟動4個子線程,strace生成4個文件oneapm.1278 oneapm.1279, oneapm.1280, oneapm.1281

oneapm.1280

線程1280不停獲取時間,然後向目標網站發送數據,發送的數據與tcpdump抓到的數據相同

 

oneapm.1279

線程1279 開啟了一個監聽,用accept()函數等待連接。 然後用read()函數從這個句柄讀取數據。句柄fd=6。

由此可知oneapm-daemon 通過一個線程開啟監聽,等待數據傳輸過來,讀取數據。然後用另外一個線程將數據發送到展示網站上。 這裡使用了socket進行本地進程間的通信。

 

2.找到socket句柄

由於socket 的fd是瞬時性的,所以無法用lsof直接看到該句柄。用gdb attach 上去。

Read調用有以下幾個點,都斷住。

Fd=6,buffer中讀出我們想要的數據。此時用lsof查看句柄信息

連接到/tmp/.oneapm-daemon.domain文件上。

 

3.找到發送數據的進程

由於只有apache2 連接了oneapm.so擴展,所以先監聽apache2。

Strace –ff –p 5046 –s 1024 –o apache

在結果文件中找到如下信息

Apache2 通過socket連接到/tmp/.oneapm-daemon.domain,向其發送數據。 通過這樣與oneapm-daemon實現進程間數據的傳遞。

 

4. 數據傳輸與收集過程

Gdb attach上apache,進入子進程模式,並對oneapm.so的幾個激活函數下斷點。

斷點命中

可以看到調用的次序zm_activate_apm,zm_deactivate_apm,zm_post_zend_deactivate_apm

打印其調用棧,這幾個函數都是在一定條件達成後,php激活zend相關函數自動調用的。

 

分析這幾個函數的代碼

1)zm_activate_apm()

zm_activate_apm調用了很重要的函數hook_start()。

Hook_start()函數如下

這邊是監控程序的核心hook入口點,apm程序對網站性能監控的hook都可以在這裡找到。

2)zm_deactivate_apm()做的就是一些反激活的事

3)zm_post_zend_deactivate_apm()

send_connect_data()

talk_to_server()

do_write()

調用過程如下

zm_post_zend_deactivate_apm()àsend_connect_data()àtalk_to_server()à

do_connect(),do_write()->send()

 

zm_post_zend_deactivate_apm()負責發送數據。

5. 代碼流程

監控階段代碼流程如上圖所示

0x04 整體流程

1) 安裝文件將oneapm.so與oneapm-daemon拷貝到對應的文件夾下,然後修改php配置文件,以實現php擴展

2) Apache啟動過程中,載入擴展oneapm.so,自動執行一些初始化函數,拉起守護進程

oneapm-daemon,並收集一些系統信息。oneapm-daemon進程創建監聽,等待本地socket連接。

3) 網站請求與一些時間條件激發apache中的oneapm.so 激活函數,開始hook收集當前的一些服務器性能信息,然後反激活,接著將這些信息通過本地socket的方式進行進程通信,連接到oneapm-daemon的監聽上,然後向其發送收集到的數據。oneapm-daemon進程接收到連接,並讀取數據,用另外一個線程向展示網站發送數據。

0x05 資源

Hook信息,位於hook_start()函數中

相關ELF文件

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved