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文件

原文地址:https://www.cnblogs.com/alert123/p/5217821.html