钩取API之代码修改方法【一】

IAT方式就不去花精力了,加了壳的程序用这方法压根用不上。

就熟悉一下代码修改方法。书上用的是隐藏进程的实例

第一种办法

一,枚举进程,给所有进程加载DLL【用远程线程注入】

二,传入需要隐藏的进程名

三,判断有没有修改过需要钩取的函数,如果还没有修改过就改掉,跳向自己的函数,同时保存好原来的值

四,在自己的替代函数里将原来的值修改回去,并再执行一次,执行完做相关处理

五,在自己的替代函数最后再钩取函数,修改跳转到替代函数

基本逻辑就是这样,像是移花接木啊。。。

DLL代码:

#define STATUS_SUCCESS                        (0x00000000L)

typedef LONG NTSTATUS;
typedef struct _LSA_UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} LSA_UNICODE_STRING, *PLSA_UNICODE_STRING, UNICODE_STRING, *PUNICODE_STRING;
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;
//+0x3c  进程名

//+0x44 进程ID

typedef NTSTATUS (WINAPI *PFZWQUERYSYSTEMINFORMATION)
                 (SYSTEM_INFORMATION_CLASS SystemInformationClass,
                  PVOID SystemInformation,
                  ULONG SystemInformationLength,
                  PULONG ReturnLength);

#define DEF_NTDLL                       ("ntdll.dll")
#define DEF_ZWQUERYSYSTEMINFORMATION    ("ZwQuerySystemInformation")

// global variable (in sharing memory)
#pragma comment(linker, "/SECTION:.SHARE,RWS")
#pragma data_seg(".SHARE")
    TCHAR g_szProcName[MAX_PATH] = {L""};
#pragma data_seg()

// 全局变量,用于存放钩取函数的前五个字节
BYTE g_pOrgBytes[5] = {0,};

BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes)
{
    FARPROC pfnOrg;
    DWORD dwOldProtect, dwAddress;
    BYTE pBuf[5] = {0xE9, 0, };
    PBYTE pByte;

// 这儿取钩取函数
    pfnOrg = (FARPROC)GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
    pByte = (PBYTE)pfnOrg;

// 判断勾取函数是否已经修改
    if( pByte[0] == 0xE9 )
        return FALSE;

// 修改保护属性
    VirtualProtect((LPVOID)pfnOrg, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

// 保存原函数的前5个字节
    memcpy(pOrgBytes, pfnOrg, 5);

// 计算跳转地址的差值
    // => XXXX = pfnNew - pfnOrg - 5
    dwAddress = (DWORD)pfnNew - (DWORD)pfnOrg - 5;
    memcpy(&pBuf[1], &dwAddress, 4);

// 将跳转代码复制到原函数
    memcpy(pfnOrg, pBuf, 5);

// 把页面保护属性修改回来
    VirtualProtect((LPVOID)pfnOrg, 5, dwOldProtect, &dwOldProtect);
    
    return TRUE;
}

//恢复
BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes)
{
    FARPROC pFunc;
    DWORD dwOldProtect;
    PBYTE pByte;

//
    pFunc = GetProcAddress(GetModuleHandleA(szDllName), szFuncName);
    pByte = (PBYTE)pFunc;

//
    if( pByte[0] != 0xE9 )
        return FALSE;

VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect);

// Unhook
    memcpy(pFunc, pOrgBytes, 5);

VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect);

return TRUE;
}

NTSTATUS WINAPI NewZwQuerySystemInformation(
                SYSTEM_INFORMATION_CLASS SystemInformationClass,
                PVOID SystemInformation,
                ULONG SystemInformationLength,
                PULONG ReturnLength)
{
    NTSTATUS status;
    FARPROC pFunc;
    PSYSTEM_PROCESS_INFORMATION pCur, pPrev;
    char szProcName[MAX_PATH] = {0,};
    
    // 先脱钩
    unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION, g_pOrgBytes);

// 执行一次
    pFunc = GetProcAddress(GetModuleHandleA(DEF_NTDLL),
                           DEF_ZWQUERYSYSTEMINFORMATION);
    status = ((PFZWQUERYSYSTEMINFORMATION)pFunc)
              (SystemInformationClass, SystemInformation,
              SystemInformationLength, ReturnLength);

if( status != STATUS_SUCCESS )
        goto __NTQUERYSYSTEMINFORMATION_END;

if( SystemInformationClass == SystemProcessInformation )
    {
        // SYSTEM_PROCESS_INFORMATION
        pCur = (PSYSTEM_PROCESS_INFORMATION)SystemInformation;

while(TRUE)
        {

//处理一个链表
            if(pCur->Reserved2[1] != NULL)
            {
                if(!_tcsicmp((PWSTR)pCur->Reserved2[1], g_szProcName))
                {
                    if(pCur->NextEntryOffset == 0)//如果已经是最后一节
                        pPrev->NextEntryOffset = 0;
                    else                                         //将自己这一节剥离
                        pPrev->NextEntryOffset += pCur->NextEntryOffset;
                }
                else        
                    pPrev = pCur;
            }

if(pCur->NextEntryOffset == 0)
                break;

// 指向下一节
            pCur = (PSYSTEM_PROCESS_INFORMATION)
                    ((ULONG)pCur + pCur->NextEntryOffset);
        }
    }

__NTQUERYSYSTEMINFORMATION_END:

// 这里居然用了一个跳转命令。。。
    hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
                 (PROC)NewZwQuerySystemInformation, g_pOrgBytes);

return status;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    char            szCurProc[MAX_PATH] = {0,};
    char            *p = NULL;

// 如果是启动这个DLL的程序就退出
    GetModuleFileNameA(NULL, szCurProc, MAX_PATH);
    p = strrchr(szCurProc, ‘\\‘);
    if( (p != NULL) && !_stricmp(p+1, "HideProc.exe") )
        return TRUE;

switch( fdwReason )
    {
        // #2. API Hooking
        case DLL_PROCESS_ATTACH :
        hook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
                     (PROC)NewZwQuerySystemInformation, g_pOrgBytes);
        break;

// #3. API Unhooking
        case DLL_PROCESS_DETACH :
        unhook_by_code(DEF_NTDLL, DEF_ZWQUERYSYSTEMINFORMATION,
                       g_pOrgBytes);
        break;
    }

return TRUE;
}

#ifdef __cplusplus
extern "C" {
#endif

//export函数,传递要隐藏的程序名。
__declspec(dllexport) void SetProcName(LPCTSTR szProcName)
{
    _tcscpy_s(g_szProcName, szProcName);
}
#ifdef __cplusplus
}
#endif

时间: 2024-10-26 22:03:23

钩取API之代码修改方法【一】的相关文章

钩取API之调试器模式

描述:当代码调试遇到INT3指令就会中断运行EXCEPTION_BREAKPOINT异常事件会被传送到调试器,此时控制权就到了调试器了,利用这种特性钩取API. 流程:将要钩取的API的起始部分修改为0xCC(INT3),控制权移到调试器后执行想实现的代码后,再修改回去重新进入运行状态. LPVOID g_pfWriteFile = NULL;CREATE_PROCESS_DEBUG_INFO g_cpdi;BYTE g_chINT3 = 0xCC, g_chOrgByte = 0; int _

git只拉取github部分代码的方法

需求:github某个项目所有代码太大,有600+M,甚至更大:只需要拉取部分代码,一是可以降低网络消耗,二是可以降低磁盘占用 分析了下空间占用情况:发现每个项目下的.git/objects/pack都很大,这应该是git的机制,使用git就避免不了下载这个东西,所以降低网络消耗的需求暂时满足不了,后续再研究吧 ~/gitlab/druid/.git/objects/pack 方法一:参考 https://blog.csdn.net/u022812849/article/details/5302

钩取API应用实例【NtCreateFile】

#include "stdafx.h"#include <tchar.h>#include <io.h>#define STATUS_SUCCESS      (0x00000000L) typedef LONG NTSTATUS;typedef struct _LSA_UNICODE_STRING { USHORT Length; USHORT MaximumLength; PWSTR Buffer;} LSA_UNICODE_STRING, *PLSA_UN

c#使用easyhook库进行API钩取

目标:使calc程序输入的数自动加1 (当别人使用时,总会得不到正确的结果,哈哈) 编写注入程序 ————————————————————————————————— class Program中的方法,注入dll到目标进程 ——————————————————————-—————————— static String ChannelName = null; static void Main(string[] args) { Int32.TryParse(args[0], out TargetPI

做web项目时对代码修改后浏览器端不生效的应对方法(持续更新)

做web项目时,经常会遇到修改了代码,但浏览器端没有生效,原因是多种多样的,我会根据我遇到的情况逐步更新解决办法 1.运行的时候采用debug模式,一般情况下使用项目部署按钮右边那个按钮下的tomcat7中的run就行,如果使用的是serves中的run serves,这种情况貌似不会自动编译 2.点击project菜单下的clean选项,在打开的窗口中选择你使用的项目,ok,这样会删除tomcat容器中关于该项目的一些信息,然后重新部署,运行 3.删除电脑中tomcat文件夹,重新解压,然后在

PCB .net Genesis脚本在没有源代码情况更改代码的工具与修改方法

记录一下发生在三个月前,在没有.net Genesis脚本源代码情况直接更改硬代码的工具与修改方法  一.背景 Genesis脚本是.net语言编写,由于外网IP地址不可用,Genesis脚本更新程序有连接到外网IP地址,直接硬代码写死了,目前此外网IP地址不通,需切换为内部IP才行但编写此程序前辈,没有留下源代码.  二..net脚本修改方法 使用Reflector工具和Reflexil插件,实现.net程序变量值修改,并生新生成exe  三. Reflector和Reflexil 工具下载地

Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数、ColModel API、事件及方法

系列索引 Web jquery表格组件 JQGrid 的使用 - 从入门到精通 开篇及索引 Web jquery表格组件 JQGrid 的使用 - 4.JQGrid参数.ColModel API.事件及方法 Web jquery表格组件 JQGrid 的使用 - 5.Pager翻页.搜索.格式化.自定义按钮 Web jquery表格组件 JQGrid 的使用 - 6.准备工作 & Hello JQGrid Web jquery表格组件 JQGrid 的使用 - 7.查询数据.编辑数据.删除数据

as关键词还有另外一个用途,那就是修改 方法 的访问控制

PHP是单继承的语言,在PHP 5.4 Traits出现之前,PHP的类无法同时从两个基类继承属性或方法.php的Traits和Go语言的组合功能类似,通过在类中使用use关键字声明要组合的Trait名称,而具体某个Trait的声明使用trait关键词,Trait不能直接实例化.具体用法请看下面的代码: <?php trait Drive { public $carName = 'trait'; public function driving() { echo "driving {$thi

Action访问Servlet API的三种方法

一.为什么要访问Servlet API ? Struts2的Action并未与Servlet API进行耦合,这是Struts2 的一个改良,从而方便了单独对Action进行测试.但是对于Web控制器而言,不访问action是不行的,Struts提供了一种比较简单的方式来访问Servlet API . 二.通常我们需要访问的Servlet API 是 HttpSession.HttpservletRequest.ServletContext,分别对应了JSP内置对象 session,reques