专栏首页逆向技术Ps回调函数.拦截驱动模块原理+实现.

Ps回调函数.拦截驱动模块原理+实现.

目录

一丶简介

主要是讲解.内核中如何拦截模块加载的. 需要熟悉.内核回调的设置 PE知识. ShellCode

二丶原理

1.原理

原理是通过回调函数. 回调函数中有 ImageBase. 使用PE解析ImageBase 得到OEP. OEP位置写入 ret等ShellCode

如何判断 是加载DLL 还是加载Sys. 可以看回调的第二个参数.(ProcessId) 如果ProcessId == 0. 则是加载Sys

PS: 在内核中解析PE需要用到 ntImage.h头文件来进行解析.

2.代码实现

#include <ntimage.h>
#include <ntddk.h>

#include <wdm.h>

ULONG_PTR g_LoadPtr = 0;


void WPONx64(KIRQL irql)
{
    UINT64 cr0 = __readcr0();
    cr0 |= 0x10000;
    _enable();
    __writecr0(cr0);
    KeLowerIrql(irql);
}



KIRQL WPOFFx64()
{
    KIRQL irql = KeRaiseIrqlToDpcLevel();
    UINT64 cr0 = __readcr0();
    cr0 &= 0xfffffffffffeffff;
    __writecr0(cr0);
    _disable();
    return irql;

}


BOOLEAN Fuck(PVOID pOep)
{
    KIRQL kirql;

    if (NULL == pOep)
        return FALSE;

    //写入字节.
    
    UCHAR FuckCode[] = { "\xB8\x22\x00\x00\xC0\xC3" };
    kirql = WPOFFx64();
    KdBreakPoint();
    memcpy(pOep, FuckCode, sizeof(FuckCode) / sizeof(FuckCode[0])); //开头写入拒绝访问错误码让其无法加载即可.
    WPONx64(kirql);
    return TRUE;
}
//根据ImageBase来获取加载模块的入口点
PVOID GetImageOep(PVOID ImageBase)
{

    PVOID pAddressOfEntryPoint = NULL;
    PIMAGE_DOS_HEADER pDosHead = NULL;
    PIMAGE_NT_HEADERS pNtHead = NULL;
    PIMAGE_FILE_HEADER pFileHead = NULL;
    PIMAGE_OPTIONAL_HEADER pOptHead = NULL;

    //开始解析
    if (ImageBase == NULL)
        return NULL;

    pDosHead = (PIMAGE_DOS_HEADER)ImageBase;
    pNtHead = (PIMAGE_NT_HEADERS)(pDosHead->e_lfanew + (char *)ImageBase);
    pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;
    pOptHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;

    //判断是否是PE头
    if (pDosHead->e_magic != 0x5A4D && pNtHead->Signature != 0x5045)
        return NULL;
    pAddressOfEntryPoint = pOptHead->AddressOfEntryPoint + (char *)ImageBase;

    return pAddressOfEntryPoint;
}

char * MyWideUnicodeStringToMutilString(PUNICODE_STRING uString)
{
    ANSI_STRING asStr;
    char *Buffer = NULL; ;
    RtlUnicodeStringToAnsiString(&asStr, uString, TRUE);
    Buffer = ExAllocatePoolWithTag(NonPagedPool, uString->MaximumLength * sizeof(wchar_t), 0);
    if (Buffer == NULL)
        return NULL;
    RtlCopyMemory(Buffer, asStr.Buffer, asStr.Length);
    return Buffer;
}
VOID pSfFilterModule(
    _In_opt_ PUNICODE_STRING FullImageName,
    _In_ HANDLE ProcessId,                // pid into which image is being mapped
    _In_ PIMAGE_INFO ImageInfo
)
{
    /*
    模块拦截思路:
    1.通过 PIMAGE_INFO->ImageBase 得到模块的ImageBase
    2.解析PE头.
    3.可选头的OEP + ImageBase = 程序运行位置
    4.在程序开头写入 ret.
    5.通过参数一,判断是不是我们想要拦截的模块.然后进行1 2 3 4步
    6.如何判断加载驱动模块还是DLL 根据参数2.ProcessId高低位判断即可. == 0加载驱动模块.否则加载DLL
    */

    
    
    PVOID pDriverOep = NULL;
    char *ComPareString = NULL;
    if (MmIsAddressValid(FullImageName))
    {
        
        if (ProcessId == 0)
        {
            //代表拦截驱动模块

            

            //判断名字是否是你想要拦截的.
            KdBreakPoint();
            
            ComPareString = MyWideUnicodeStringToMutilString(FullImageName);
            if (ComPareString == NULL)
                return;

            if (strstr(ComPareString,"1.sys"))
            {
                KdBreakPoint();
                KdPrint(("你要拦截的驱动模块名字为: %wZ \r\n", FullImageName));
                pDriverOep = GetImageOep(ImageInfo->ImageBase);

                //判断拦截的名字是否是你想要拦截的
                if (pDriverOep != NULL)
                {
                    Fuck(pDriverOep);
                }
            }
            
        }
        //输出调试
        
    }
    
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)
{
    ULONG iCount = 0;
    NTSTATUS ntStatus;
    pDriverObj->DriverUnload = DriverUnLoad;
    ntStatus = InitDeviceAnSybolicLinkName(pDriverObj);
    if (!NT_SUCCESS(ntStatus))
    {
        return ntStatus;
    }

    ntStatus = InitDisPatchFunction(pDriverObj);
    if (!NT_SUCCESS(ntStatus))
    {
        return ntStatus;
    }


    PsSetLoadImageNotifyRoutine(pSfFilterModule);
    return STATUS_SUCCESS;
}

3.效果

win7 64 sp1 下测试.

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 遍历进程,获取当前进程下进程的路径.(获得全路径)

    IBinary
  • IAT Hook

    我们知道PE有两种状态.第一种.在文件中的状态. 所以才有 VA 转 FOA等等的互相转换. 扯多了. 在文件状态. IAT表(firstThunk)跟 I...

    IBinary
  • 内存Exe加载,PEloder简单原理

    而对于我们来说.其实就是 针对PE文件的 NT头 节表数据 重定位表 导入表 等进行操作.

    IBinary
  • ffmpeg+sdl播放类

    前段时间一直捣鼓ffmpeg,觉得还是VLC比较亲切,虽然我现在都不知道VLC怎么用了。 除了雷神的博客,主要参考的还是这个博客:http://blog.yun...

    _gongluck
  • mongo的身份验证和授权

    刚装好的mongo,准备登陆进去测一把的,结果就给我报这个错,鄙人是新手,还不太清楚这个,现学一下~

    拓荒者
  • day7、用户登陆出现-bash-4.1$错误的原因

    有时候在使用用户登陆Linux系统时会出现-bash-4.1$错误,不显示用户名,路径信息。 原因:用户家目录里面与环境变量有关的文件被删除所导致的 .bash...

    863987322
  • 【go】剑指offer:求一个数的整数次方

    基于以上的思路,其实是有bug的,假如输入的n为0或者小于0呢?因此我们需要对我们的代码进行改进。若n < 0 ,其实我们求出的是一个倒数,即-n次方的倒数。那...

    陌无崖
  • 创建局域网方案!!!!!--安全的物联网技术方案使用说明与管理

    有时候有需要使用专用网络的需求,让一些资源只能在该专用网络下访问,所以需要使用vpn服务。

    嘘、小点声
  • Bitmap 源码阅读笔记

    导语: Android 系统上的图片的处理,跟Bitmap 这个类脱不了关系,我们有必要去深入阅读里面的源码,以便在工作中能更好的处理Bitmap相关的问题...

    MelonTeam
  • python flask web基本结构 登录模块 常用

    flask-login werkzeug itsdangerous flask-mail flask-bootstrap flask-wtf

    用户5760343

扫码关注云+社区

领取腾讯云代金券