zoukankan      html  css  js  c++  java
  • hook技术--代码hook

    1.简介:

    对于IAT hook 方法,它只能hook掉在iat中的API,如果是通过动态加载的就不行了
    因为动态加载的dll的API不在iat中,而是动态生成的.
    这时可以预先加载该dll和API,并对API前几个字节进行保存然后修改成
    跳转到自己的某函数中,然后进行一些操作后可以再跳回到原来的API.
    这就是所谓的API修改hook.

    2.以hook掉任务管理器的进程遍历功能,为例,用此来隐藏calc.exe这个进程

    windows上ring3层的遍历进程API底层都调用了

    ZwQuerySystemInformation 函数 该函数在ntdll中,但没有公开

    在网上寻找该API的参数和返回值信息,在代码中体现

    代码思路是: 先获取ZwQuerySystemInformation的地址,保存前5个字节的代码. 再覆盖为一个跳转到我们实现的一个伪ZwQuerySystemInformation

    函数地址的jmp指令的机器代码.在我们的函数中找到calc.exe的进程名,然后再跳过这个节点即可.

    #include "stdafx.h"
    #include <Windows.h>
    #include <wchar.h>
    #include <malloc.h>
    #include<stdio.h>
    #define funcName "ZwQuerySystemInformation"
    #define dllName "ntdll.dll"
    #define processName L"calc.exe"
    typedef LONG NTSTATUS;
    typedef enum _SYSTEM_INFORMATION_CLASS {
        SystemBasicInformation = 0,
        SystemPerformanceInformation = 2,
        SystemTimeOfDayInformation = 3,
        SystemProcessInformation = 5,
        SystemProcessorPerformanceInformation = 8,
        SystemInterruptInformation = 23,
        SystemExceptionInformation = 33,
        SystemRegistryQuotaInformation = 37,
        SystemLookasideInformation = 45
    } SYSTEM_INFORMATION_CLASS;
    
    typedef struct _SYSTEM_PROCESS_INFORMATION {
        ULONG NextEntryOffset;
        ULONG NumberOfThreads;
        BYTE Reserved1[48];
        PVOID Reserved2[3];
        HANDLE UniqueProcessId;
        PVOID Reserved3;
        ULONG HandleCount;
        BYTE Reserved4[4];
        PVOID Reserved5[11];
        SIZE_T PeakPagefileUsage;
        SIZE_T PrivatePageCount;
        LARGE_INTEGER Reserved6[6];
    } SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;
    
    typedef NTSTATUS(WINAPI *PFZWQUERYSYSTEMINFORMATION)
    (SYSTEM_INFORMATION_CLASS SystemInformationClass,
        PVOID SystemInformation,
        ULONG SystemInformationLength,
        PULONG ReturnLength);
    
    
    BYTE orgCode[5];//原始指令
    BYTE fakeCode[5]; //伪造的jmp指令
    DWORD funcBase;  //我们的函数基址
    
     //   char debug[100]={0};
    
    DWORD WINAPI myZwQuerySystemInformation
    (SYSTEM_INFORMATION_CLASS SystemInformationClass,
        PVOID SystemInformation,
        ULONG SystemInformationLength,
        PULONG ReturnLength);
    
    
    DWORD hook(DWORD funcbase, DWORD fakeFunc);
    DWORD unhook(DWORD funcbase);
    BOOL APIENTRY DllMain( HMODULE hModule,
                           DWORD  ul_reason_for_call,
                           LPVOID lpReserved
                         )
    {
      //获取目标函数基址和伪造函数基址 DWORD fakeFunc; funcBase
    = (DWORD)GetProcAddress(GetModuleHandleA(dllName), funcName); fakeFunc = (DWORD)myZwQuerySystemInformation; switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH:     //加载时就hook掉 hook(funcBase, fakeFunc); break; case DLL_PROCESS_DETACH: unhook(funcBase); break; } return TRUE; } DWORD hook(DWORD funcbase, DWORD fakeFunc) { DWORD page;
    //如果已经被hook了就不再继续
    if(*(BYTE*)funcbase==0xe9) { return 0; } VirtualProtect((LPVOID)funcbase, 5, PAGE_EXECUTE_READWRITE, &page); memcpy(orgCode, (LPVOID)funcbase, 5); fakeCode[0] = 0xe9; DWORD opCode = fakeFunc -funcBase - 5;//jmp指令的操作码计算公式为:目标地址-当前指令地址-5 // sprintf(debug,"hook fakeFunc is %p, funcbase is %p",fakeFunc,funcbase); memcpy(fakeCode + 1, &opCode, 4);//填充为指令 memcpy((LPVOID)funcBase, fakeCode, 5); //修改代码 VirtualProtect((LPVOID)funcbase, 5, page, &page); return 1; } DWORD unhook(DWORD funcbase) { DWORD page; if(*(BYTE*)funcbase!=0xe9) { return 0; } VirtualProtect((LPVOID)funcbase, 5, PAGE_EXECUTE_READWRITE, &page); memcpy((LPVOID)funcBase, orgCode, 4); //恢复代码 VirtualProtect((LPVOID)funcbase, 5, page, &page); return 1; } DWORD WINAPI myZwQuerySystemInformation (SYSTEM_INFORMATION_CLASS SystemInformationClass, PVOID SystemInformation, ULONG SystemInformationLength, PULONG ReturnLength) /* 这个函数的hook和一般的函数不同,这种函数属于查询类的函数,真正有用的信息 在该函数调用完了后才会写到缓冲区类的参数,而调用前的参数信息基本没用, 因此我们要对该函数进行正常调用,完后了再截取信息 */ { DWORD fakeFunc; funcBase = (DWORD)GetProcAddress(GetModuleHandleA(dllName), funcName); fakeFunc = (DWORD)myZwQuerySystemInformation; PSYSTEM_PROCESS_INFORMATION p, pPre; unhook(funcBase); //取消hook以正常调用 DWORD status=4; status=((PFZWQUERYSYSTEMINFORMATION)funcBase)(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);//正常调用该函数 if(status!=0) { hook(funcBase, fakeFunc); //hook住 return 0; } if (SystemInformationClass== SystemProcessInformation) //只对查询进程的信息感兴趣 { p = ((PSYSTEM_PROCESS_INFORMATION)SystemInformation); while (1) { if(p->Reserved2[1]!=0) { if (lstrcmpiW((WCHAR*)p->Reserved2[1], processName)==0) { if (p->NextEntryOffset==0)//说明是最后一个了 { pPre->NextEntryOffset = 0; //将后面一个节点的next指针置0即可 } else { //跳过本节点 NextEntryOffset字段是相对于本节点的偏移,而不是绝对地址 //当当前节点是第一个节点时这个式子也成立 pPre->NextEntryOffset += p->NextEntryOffset; } } else { pPre = p; } } if(p->NextEntryOffset==0) { break; } p =((PSYSTEM_PROCESS_INFORMATION)((DWORD)p + p->NextEntryOffset)); } } hook(funcBase, fakeFunc); //hook住 return 1; }
  • 相关阅读:
    MYSQL mysql.user表中权限对应的解释
    MYSQL LOCK IN SHARE MODE&FOR UPDATE
    什么是索引
    ol,li,ul,dl,dt,dd
    CSS类与选择器【转】http://www.cnblogs.com/duanhuajian/archive/2012/12/17/2821524.html
    bootstrap笔记
    iPhone应用程序开发基础之一: IBOutlet与IBAction
    Objective-C中的加号与减号
    Linux下*.tar.gz文件解压缩命令
    【PHP+MySQL学习笔记】php操作MySQL数据库中语句
  • 原文地址:https://www.cnblogs.com/freesec/p/6560935.html
Copyright © 2011-2022 走看看