Skip to content

3 Client以及Hook代码框架

jialuhu edited this page May 13, 2019 · 5 revisions

hook.c框架

hook框架主要由四个函数模块和两个枚举类型组成。

函数模块 功能
int open(const char *pathname, int flags, ...) 劫持本地被监测目录的open调用
int close(int fd) 劫持本地被监测目录的close调用
enum MONITOR_STATE Unix_Socket(enum TYPE_HOOK types, char *pathname) Unix域套接字创建以及连接
enum MONITOR_STATE prase_monitor_package(const char *package) 接收监测工具进程返回的状态(备份是否成功,取备份是否成功)
Socket 封装了一些基本的socket系列函数
枚举类型 含义
enum TYPE_HOOK{OPEN_CALL=0,CLOSE_CALL} 启动hook函数的系统调用:open或者为close
enum MONITOR_STATE{OPEN_SAVE_OK,CLOSE_GET_OK,OPEN_SAVE_FAILT,CLOSE_GET_FAILT,USOCKET_FAILT,UCONNECT_FAILT,UWRITE_FAILT} 备份和取备份成功,以及失败返回

Client.cpp

client框架主要由线程池+事件封装类队列和epoll组成

用途
Monitored_event Unix域套接字事件封装,即本地进程事件封装
类模版 用途
threadpool 线程池处理任务队列中的任务事件
epoll 事件表 模式
epoll相关函数 Unix域的套接字、与远程服务器连接的套接字 本地Unix套接字采用ET模式与非EPOLLOENSHOT模式,远程连接的套接字采用ET模式+EPOLLONESHOT模式

threadpool

类模版成员函数 功能
threadpool() 构造函数,创建线程并且进入线程执行函数
~threadpool() 析构函数
bool addjob(T* request) 往事件队列中添加一个事件
void run() 轮询等待任务队列有事件,并且从队列中拿出事件进行处理
线程池与监测工具的接口 功能
request->do_process() 调用到事件类的接口函数

Monitored_event类

类成员函数 功能
/被监测事件含参构造并初始化/
void init(int ed, int i_s, int u_s) 被监测事件含参构造并初始化
void close_monitored() 关闭连接
void do_process() 分析被监测事件的类型,线程池轮询事件队列的接口
bool u_write() Unix写到hook.c进程函数
bool i_write() 与远端服务器连接写函数
bool u_read() Unix读取hook.c进程发送包函数
bool i_read() 与远端服务器连接的函数
void Monitored_modfd(int epfd, int fd, int ev) 因为是EPOLLNESHOT,所以每次要修改epoll事件表
bool get_line(const char *test_buf) 获取协议包头的每行并且解析
Request_State parse_read_buf() 通过解析Unix套接字的读缓冲区,判断是open调用还是close调用被劫持
void fill_swrite_buf(Request_State state) 填写向服务器发送的写缓冲区,根据请求类型进行填写响应包
void fill_uwrite_buf(Request_State state) 填写Unix的发送缓冲区,根据请求填写响应包
class Monitored_event{
    public:
        /*Unix套接字读缓冲区有三种状态:OPEN请求,CLOSE请求,重复打开同一个文件*/
        enum Request_State{OPEN_SAVE, CLOSE_GET, REPEAT_FILE};
        /*解析有两种状态,一种是解析头部,另一种是还有文件内容*/
        enum Parse_State{HEAD, CONTENT};
    public:
        static const int READ_BUF_SIZE = 2048;
        static const int WRITE_BUF_SIZE = 1024;
    private:
        static int epfd;//所有被监测的事件共同使用一个epoll注册事件
        static int i_socketfd;//所有被监测的事件共同使用一个远程连接
        int u_socketfd;//Unix套接字
        static int Monitored_number;//所有被监测事件的个数

        Parse_State p_state;//解析头部和内容,状态转移标志

        char *line_buf;//读取到的每一行的头指针
        int now_index;//当前解析了多少字节
        int file_length;//文件的大小
        map<string, int> repeat_path;//查看是否是重复文件
    public:
        /*由于之后用的是类数组形式,初始化类成员统一在init成员函数中进行*/
        Monitored_event(){}
        ~Monitored_event(){}
    public:
        /*被监测事件含参构造并初始化*/
        void init(int ed, int i_s, int u_s);
        /*关闭连接(考虑之中,因为不能关闭网络套接字和Unix套接字)*/
        void close_monitored();
        /*分析被监测事件的类型,线程池轮询事件队列的接口*/
        void do_process();

        /*Unix写到hook.c进程函数*/
        bool u_write();

        /*与远端服务器连接写函数*/
        bool i_write();


        /*Unix读取hook.c进程发送包函数*/
        bool u_read();

        /*与远端服务器连接的函数*/
        bool i_read();

    private:
        /*unix套接字的读取缓冲区*/
        char unix_read_buf[READ_BUF_SIZE];

        /*TCP套接字读取缓冲区,即服务器应答缓冲区*/
        char server_read_buf[READ_BUF_SIZE];

        /*unix套接字的发送缓冲区*/
        char unix_write_buf[READ_BUF_SIZE];

        /*TCP套接字发送缓冲区*/
        char server_write_buf[READ_BUF_SIZE];

    private:
    /*因为是EPOLLNESHOT,所以每次要修改epoll事件表*/
    void Monitored_modfd(int epfd, int fd, int ev);

    /*获取每行并且解析*/
    bool get_line(const char *test_buf);

    /*通过解析Unix套接字的读缓冲区,判断是open调用还是close调用被劫持*/
    Request_State parse_read_buf();

    /*填写向服务器发送的写缓冲区,根据请求类型进行填写响应包*/
    void fill_swrite_buf(Request_State state);

    /*填写Unix的发送缓冲区,根据请求填写响应包*/
    void fill_uwrite_buf(Request_State state);

};

类方法的实现细节中会相继添加一些类成员或者是类成员函数

Clone this wiki locally