WIN7-X64内核模式下编程实现导出表列表查看

内核模式下查看导出表需要注意的事项比在用户模式下要考虑更加周详;

X64环境倒不是变化太多,指针定是64位的,数据数据及指针指向的数据类型需要注意;

不费话,直接上源码,VS2010+WDK7600下编译通过:

///
/// @file aux_list.c
/// @author cntom90151
/// @date2015-09-24
/// 

#include <ntddk.h>
#include <WinDef.h>
#include <aux_klib.h>

#pragma comment(lib,"aux_klib.lib")    

#define TAG        ‘test‘
#define PtrFromRva(xbase,rva)    (((PBYTE)xbase)+rva)

// 提供一个Unload函数只是为了
VOID DriverUnload(PDRIVER_OBJECT driver)
{
    // 但是实际上我们什么都不做,只打印一句话:
    // #if DBG
    //    DbgBreakPoint();
    // #endif
    KdPrint(("first: Our driver is unloading…\r\n"));
}

NTSTATUS ExpList(PVOID imagebase)
{
    //PVOID LoadAddress=(PVOID)*(PVOID*)imagebase;
    NTSTATUS status=0;
    PIMAGE_EXPORT_DIRECTORY ExportDirectory;
    PIMAGE_DATA_DIRECTORY ExportDataDirectory;
    PIMAGE_NT_HEADERS NtHeader;
    PIMAGE_DOS_HEADER DosHeader=(PIMAGE_DOS_HEADER)imagebase;

    ULONG Index;
    PULONG FuncRvaArray;
    PUSHORT OrdArray;
    PULONG NameArray;

    if (IMAGE_DOS_SIGNATURE!=DosHeader->e_magic)
    {
        KdPrint(("No Dos Header!\n"));
        return status;
    }
    NtHeader=(PIMAGE_NT_HEADERS)PtrFromRva(DosHeader,DosHeader->e_lfanew);
    if (IMAGE_NT_SIGNATURE!=NtHeader->Signature)
    {
        KdPrint(("Not Nt File!\n"));
        return status;
    }

    ExportDataDirectory=&NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    ExportDirectory=(PIMAGE_EXPORT_DIRECTORY)PtrFromRva(imagebase,ExportDataDirectory->VirtualAddress);
    //这上下两个可以对比
    ExportDirectory=AuxKlibGetImageExportDirectory(imagebase);

    if (!MmIsAddressValid(ExportDirectory) || ExportDirectory->NumberOfFunctions==0 || ExportDirectory->AddressOfFunctions==0 || ExportDirectory->AddressOfNameOrdinals==0 || ExportDirectory->AddressOfNames==0 )
    {
        KdPrint(("no export....\n"));
        return status;
    }

    FuncRvaArray=(PULONG)PtrFromRva(imagebase,ExportDirectory->AddressOfFunctions);
    OrdArray=(PUSHORT)PtrFromRva(imagebase,ExportDirectory->AddressOfNameOrdinals);
    NameArray=(PULONG)PtrFromRva(imagebase,ExportDirectory->AddressOfNames);
    for (Index=0;Index<ExportDirectory->NumberOfNames;Index++)
    {
        USHORT Ordinal=(USHORT)OrdArray[Index]+(USHORT)ExportDirectory->Base;
        ULONG FunRva=FuncRvaArray[Ordinal-ExportDirectory->Base];
        if (FunRva>=ExportDataDirectory->VirtualAddress && FunRva<ExportDataDirectory->VirtualAddress+ExportDataDirectory->Size)
        {
            KdPrint(("It‘s a forwarders\n"));
            continue;
        }
        else
        {
            KdPrint(("%4x   %s\n",FunRva,PtrFromRva(imagebase,NameArray[Index])));
        }
    }
    return status;
}

NTSTATUS Aux_Test()
{
    NTSTATUS status;
    ULONG modsize;
    ULONG numofmod;
    AUX_MODULE_EXTENDED_INFO *mod;
    ULONG i;

    PVOID imagebase;

    KdPrint(("Aux_Klib testing ......\n\n"));
    status=AuxKlibInitialize();
    if (!NT_SUCCESS(status))
    {
        KdPrint(("AuxKlibInitialize failed!\n"));
        return status;
    }
    status=AuxKlibQueryModuleInformation(&modsize,sizeof(AUX_MODULE_EXTENDED_INFO),NULL);
    if (!NT_SUCCESS(status) || modsize==0)
    {
        KdPrint(("first query failed!\n"));
        return status;
    }
    numofmod=modsize / sizeof(AUX_MODULE_EXTENDED_INFO);
    mod=(AUX_MODULE_EXTENDED_INFO*)ExAllocatePoolWithTag(PagedPool,modsize,TAG);
    if(mod==NULL)
    {
        status=STATUS_INSUFFICIENT_RESOURCES;
        KdPrint(("insufficient resouces!\n"));
        return status;
    }
    RtlZeroMemory(mod,modsize);
    status=AuxKlibQueryModuleInformation(&modsize,sizeof(AUX_MODULE_EXTENDED_INFO),mod);
    if (!NT_SUCCESS(status))
    {
        ExFreePoolWithTag(mod,TAG);
        KdPrint(("Query Failed!\n"));
        return status;
    }
    for (i=0;i<numofmod;i++)
    {
        KdPrint(("Load order:%d\n",i));
        KdPrint(("FileName:%s\n",mod[i].FullPathName+mod[i].FileNameOffset));
        KdPrint(("ImageBase:%p\n",mod[i].BasicInfo.ImageBase));
        KdPrint(("ImageSize:0x%08X\n",mod[i].ImageSize));
        KdPrint(("\n\n"));
        imagebase=mod[i].BasicInfo.ImageBase;    

        /*if (i==128 || i==3)
            DbgBreakPoint();*/
        if (!MmIsAddressValid(imagebase))
            continue;
        ExpList(imagebase);
    }
    ExFreePoolWithTag(mod,TAG);
    return status;
}

// DriverEntry,入口函数。相当于main。
NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    // 设置一个卸载函数便于这个函数能退出。
    driver->DriverUnload = DriverUnload;

     #if DBG
        DbgBreakPoint();
     #endif
    // 这是我们的内核模块的入口,可以在这里写入我们想写的东西。
    // 我在这里打印一句话。因为”Hello,world” 常常被高手耻笑,所以
    // 我们打印一点别的。
    KdPrint(("first: Hello, my salary!\r\n"));
    Aux_Test();

    return STATUS_SUCCESS;
}
时间: 2025-01-02 16:34:25

WIN7-X64内核模式下编程实现导出表列表查看的相关文章

Windows核心编程笔记(7)----内核模式下的线程同步

1.内核对象同步与用户模式下同步对比 使用内核对象的唯一缺点就是性能,调用内核对象函数时,调用线程必须从用户模式切换到内核模式,这种切换是相当 耗时的. 内核对象(进程.线程.作业)要么处于触发态,要么处于未触发状态.进程内核对象在创建时总是处于未触发状态, 当进程终止时,操作系统会自动使进程内核对象变成触发状态.当进程内核对象处于触发状态后,将永远保持这种状态, 再也不能变回未触发状态. 2.等待内核对象 WaitForSingleObject等待单个内核对象,WaitForMultipleO

Windows内核函数(3) - 内核模式下的注册表操作

Windows内核函数(3) - 内核模式下的注册表操作 2010-12-13 13:37:16|  分类: 驱动编程 |  标签:status  hkey  ulsize  注册  kdprint  |举报|字号 订阅 注册表里的几个概念: 1.       创建关闭注册表项 NTSTATUS   ZwCreateKey(    OUT PHANDLE  KeyHandle,    IN ACCESS_MASK  DesiredAccess, //访问权限,一般为KEY_ALL_ACCLESS

YJX_Driver_038_内核模式下的字串操作

1. 内核模式下的字串操作 A.ASCII字符串和UNICODE字符串 B.ANSI_STRING字符串和UNICODE_STRING字符串 C.字符串的初始化与销毁 D.字符串复制,比较,(大小写,整数和字串)相互转换 E.ANSI_STRING字符串和UNICODE_STRING字符串相互转换 2. A.ASNI字符串和UNICODE字符串 在C语言中,有ANSI和UNICODE 两个不同字串类型. char* s1="abc"; //CHAR * s1="abc&quo

转:Windows8内核模式下开发NDIS应用-NDIS Filter讲解

http://blog.csdn.net/itcastcpp/article/details/7752075 在Win8系统下开发驱动程序,需要数字证书,还需要驱动签名认证.不能像XP下面那样疯狂滴耍流氓了. 由于Win8系统的内核做了大幅度的修改,它和XP系统的内核起了很大的变化,最显著的就是刚才说的:需要签名和证书.  还有就是:不能随意的HOOK SSDT了. 在开发NDIS驱动程序的时候,WDK开发包提供了一个新的框架,叫着NDIS FilterNDIS Filter是一个例子工程.假入

linux 和win7 双系统模式下 忘记win7 密码的修改方法

首先登陆linux系统,在linux 系统下找到win7系统的安装盘(比如为C盘), (1)进入到C://windows/system32下 找到osk.exe 文件,并将其剪切到其他的地方(记住这个地方,后面还会将此文件粘贴回来的) (2)将C://windows/system32文件下的cmd.exe 重命名为osk.exe (3)关机,开机进入win7系统,在登陆界面的左下角有“轻松访问”,在弹出的窗口中勾选“启动屏幕键盘”,弹出确定命令提示符 (4)在命令提示符下输入 net user

x64 release模式下mysql编译连接错误解决办法

系统:win8 64位 MySQL 5.7 32 原来项目是debug 32位编译的 后来改成release 64位  结果编译没错 连接时候错误  无法解决 的外部符号之类的 解决办法: 1  下载x64位的dll ,lib文件 下载链接:点击打开链接 2  将libmysql64.lib以及libmysql64.dll拷贝到数据库安装目录下面,也就是原来libmysql.lib同级目录下面 3 我的程序里面lib是这样导进去的.所以我在这里改成了libmysql64.lib #pragma

内核模式下的文件操作

1.文件的创建 对文件的创建或者打开都是通过内核函数ZwCreateFile实现的.和Windows API类似,这个内核函数返回一个文件句柄,文件的所有操作都是依靠这个句柄进行操作的.在文件操作完毕后,要关闭这个文件句柄. NTSTATUS     ZwCreateFile(     OUT PHANDLE  FileHandle,     IN ACCESS_MASK  DesiredAccess,     IN POBJECT_ATTRIBUTES  ObjectAttributes,  

内核模式下的注册表操作

注册表操作 注册表里的几个概念: 1.       创建关闭注册表项 NTSTATUS    ZwCreateKey(     OUT PHANDLE  KeyHandle,     IN ACCESS_MASK  DesiredAccess, //访问权限,一般为KEY_ALL_ACCLESS     IN POBJECT_ATTRIBUTES  ObjectAttributes,     IN ULONG  TitleIndex, //一般为NULL     IN PUNICODE_STRI

内核模式下的字符串操作

分类: WINDOWS 1)ASCII字符串和宽字符串    在应用程序中使用两种字符:a) char型字符串,负责记录ANSI字符集,它是指向一个char数组的指针,每个char型变量大小是一个字节,字符串是以0标志字符串结束的:b) wchar_t型的宽字符串,负责描述unicode字符集,它是指向一个wchar_t数组的指针,wchar_t字符大小为两个字节,字符串以0标志字符串结束.   例: ANSI字符构造如下:   char *str1 = "ASCE";   UNICO