HOOK这是一种思想

1、H 0 0 K:
 不知道何时开始,我不喜欢叫这些知识为技术,喜欢把这些知识叫作思想。技术只是实现思想的一种行为。
 HOOK这是一个很古老的话题,我见过最先的帖子日期在2004年左右,而我2018年才学习,不变的是思想。windows


2、用户层:
 windows下用户层被泛指三环,上层社会,比较高端繁华的地方,让人向往,确实很棒。数组


3、内核层:
 windows下内核层泛指零环,底层社会,硬件、驱动设备等等协调工做,无时无刻输送着劳动成果,他们没有华丽外表封装本身,可是他们并不丑陋,相反的是他们真的很"伟大"。

4、聊聊那些HOOK先关的学问
 那时候的人真聪明,想出各类办法去绕过、截获,利用本来的轨道办一些本身事情,简单说这就是我理解的Hook。
HOOK这是一种思想
 为何放上去一张很Lol的图呢?这是我第一次理解、见到HOOK的样子,我仍然觉着他很温馨。之前也总喜欢用工具画一些精美的图片,如今除了写文档报告,都是用这种草稿图,感受更为亲切。
 Hook是有目的,有需求点,才去截获某一个过程,去实现本身的功能又不影响系统正常的运转。
 Hook手段满天飞,inlinehook、IAThook、IDThook、Objecthook、SSDThook,很遗憾很遗憾,除了新鲜感,如今的学习彻底体会不到那个年代的乐趣,这是我接触Hook的感触。

Inlinehook: jmp跳转,我的感受跳转的水平决定你的代码的稳定性。注意会破坏栈顶的5个字节,由于jmp 0x...会占用函数开始前5个字节,先读取原函数的前5个字节保存,而后在进行替换jmp跳转,执行jmp之后,要执行保存的原函数机器码,而后在跳到jmp下一条指令执行。
HOOK这是一种思想ide


IAThook:
 了解PE的人知道IAT(import address table),脱壳过程当中被加密最频繁的地方,开辟虚拟空间加密、解密IAT。在PE头中扩展头里面最后一个数组(数据目录表)中的第2项(下标1)与第12项(下标11)均可以找到对应IAT的RVA。
 《windows PE权威指南中》导入表的结构又称双桥结构,其中一条桥在加载到内存后就会被填充成IAT(FirstThunk),而经过寻找另外一条桥INT(OriginalFirstThunk)实现函数绑定。因此单桥没法进行函数绑定其实INT与IAT在文件中指向的是同一个结构体_IMAGE_THUNK_DATA32这种结构体,可是加载到内存后会把IAT填充成正确的函数地址,可执行程序才能在内存中找IAT调用正确的函数地址。
 说道这里你应该明白什么是IAT:保存加载到内存后正确的函数地址数组。Iathook就很明显了,替换函数地址,从而该进程或者线程调用函数的时候,去IAT找到的是咱们本身的函数地址便可。
HOOK这是一种思想
笼统的说inthook分为三步,如上图所示:
第一步、你要知道应用程序在调用函数的时候会去找IAT,获取IAT中保存的地址,知道了这些东西之后,你知道去截获、替换的是什么,就是地址。
第二步、咱们找到IAT,通常状况下咱们不去找IAT,咱们只须要经过GetProcAddress()或者直接用函数名(函数名编译器看来就是地址)就能够获取。而后找到被应用程序调用的函数,如何去找呢?最简单的办法逆向看一看它调用了那些函数就好了。
第三步、替换IAT表中原来函数地址,替换前先保存原地址,备份一下,而后把本身函数地址填充上去便可。函数

那么替换这些能干一些什么事情呢?看两张图
结束进程失败:
HOOK这是一种思想
挂起进程失败:
HOOK这是一种思想
360进程用procexp.exe或则任务管理器没法结束没法挂起呢?虽然不必定用iathook,可是用iathook是能够作到的。
 上一篇博客写的双进程,先挂起单个进程,就能够破掉双进程。hook能够保护你不被挂起,不被结束,比起双进程守护更为稳定实用,一样复杂程度也要高不少。工具

改进后的双进程保护程序:
先来看看这个功能:
HOOK这是一种思想性能

 基于mfc窗口,拖拽须要保护的可执行文件。可是这个进程是能够被结束的,利用线程回调检测被保护的进程状态,若是被结束,马上新建立新的进程,而后使用等待函数等待响应,这样就不会一直循环影响系统性能
 这里没有用任何的hook知识,用到了建立快照,3环的进程遍历,以及建立线程回调线程回调好处不影响当前进程的操做流程,并且暂停保护功能只须要将线程挂起便可、开启保护功能只须要将该线程唤醒,大大的节省了代码量及运行效率。(如下代码未用这种思路正常关闭线程)
 仍是有一些学习价值,因此把代码贴上来,相关的地方都给了详细的注释,这里再也不啰嗦。学习

代码实现以下:
须要类中声明、定义的变量及函数:this

// This Process True?
    BOOL IsCurrentProcessTrue();

    // CallbackFunctionHandle
    HANDLE m_Handle = NULL;

    // DriverObject
    HANDLE hDriver = INVALID_HANDLE_VALUE;

    // SavePid
    static CString g_PathValue;

    // GetProcessFileName
    static CString g_FilePath;

主要实现代码:加密

// The CallBack Function
DWORD WINAPI ThreadPrcCallBack(LPVOID lparameter)
{
    ProcessProtectMaster *pDlg = (ProcessProtectMaster*)lparameter;

    STARTUPINFO g_si = {};

    PROCESS_INFORMATION g_pi = {};

    while (true)
    {
        // 若是遍历进程发现Pid为假(开启新的进程)
        if (!pDlg->IsCurrentProcessTrue())
        {
            CreateProcess(pDlg->g_FilePath, NULL, NULL, NULL, FALSE, CREATE_NEW_CONSOLE, NULL, NULL, &g_si, &g_pi);

            WaitForSingleObject(g_pi.hProcess, INFINITE);

            CloseHandle(g_pi.hProcess);

            CloseHandle(g_pi.hThread);
        }
    }

    return 1;
}

// Is Process True?
BOOL ProcessProtectMaster::IsCurrentProcessTrue()
{
    HANDLE hProcess = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

    if (hProcess == INVALID_HANDLE_VALUE)
    {
        AfxMessageBox(L"建立快照失败");

        return FALSE; 
    }

    PROCESSENTRY32W p_32 = { sizeof(PROCESSENTRY32W) };

    if (!Process32First(hProcess, &p_32))
    {
        AfxMessageBox(L"Process32First falure!");
        CloseHandle(hProcess);
        return FALSE;
    }

    do{
        // 经过进程句柄获取文件映像路径
        // GetProcessImageFileName(hProcess, Pathbuf, MAX_PATH);
        // 强转CString对比能够用==
        CString temp = p_32.szExeFile;
        // 若是检测到有被保护进程则返回为真
        if (g_PathValue == temp)
            return TRUE;

    } while (Process32Next(hProcess, &p_32));

    // 没有检测到被保护进程为假
    return FALSE;
}

// Start Process_Protect
void ProcessProtectMaster::OnBnClickedButton1()
{
    HANDLE hProcess = INVALID_HANDLE_VALUE;

    // 1. 接收输入的PID
    UpdateData();

    // 1.1 把获取的PID保存在静态变量中(回调函数会用)
    g_FilePath = m_Edit;

    // 1.2 获取文件名
    int nPos = g_FilePath.ReverseFind(_T('\\'));

    g_PathValue = g_FilePath.Mid(nPos + 1);

    // 2. 判断当前进程是否有效
    if (!IsCurrentProcessTrue())
    {
        AfxMessageBox(L"Process Flase");

        return;
    }

    // 3.显示开启保护进程
    m_ShowValue.SetWindowTextW(L"已开启保护");

    // 4. 保护当前PID(一直检测PID,当进程被结束当即打开新的进程)
    m_Handle = CreateThread(NULL, NULL, ThreadPrcCallBack, (LPVOID)this, NULL, NULL);

}

// Stop Process_Protect
void ProcessProtectMaster::OnBnClickedButton2()
{
    // 取消保护
    DWORD nRet = TerminateThread(m_Handle, NULL);

    if (nRet)
    {
        AfxMessageBox(L"进程守护关闭");

        m_StatucShow = "未启用";

        // 关闭状态更新到窗口 
        UpdateData(FALSE);
    }
    else
        // 获取回调线程的pid
        // DWORD t_Pid = GetThreadId(m_Handle);
        // 能够cmd Kill -9 pid
        AfxMessageBox(L"请从新尝试");

}

// The Response File Receive
void ProcessProtectMaster::OnDropFiles(HDROP hDropInfo)
{
    // 1.得到拖拽数目
    int DropCount = DragQueryFile(hDropInfo, -1, NULL, 0);

    // 2.保存获取的路径信息
    char wcStr[MAX_PATH] = {};

    CString str;

    for (int i = 0; i < DropCount; i++)
    {
        // 3.记得清空字符串
        wcStr[0] = 0;

        // 4.获取路径名
        DragQueryFileA(hDropInfo, i, wcStr, MAX_PATH);

        str = wcStr;
    }

    // 直接用控件绑定变量会出现缓冲区太小问题
    m_Edit = str;

    UpdateData(FALSE);

    // 5.释放内存
    DragFinish(hDropInfo);

    CDialogEx::OnDropFiles(hDropInfo);
}

HOOK这是一种思想

 关于这两个功能一个是IAThook,一个是ssdthook。一个三环,一个零环,Hook思想是不分三环仍是零环的,零环也一样有iathook、inlinehook,他并非三环的专属。下次博客更新内容是与windows内核一些东西,顺带把hook源码讲解一下与你们分享。线程