在windows平台做逆向、外挂等,经常需要调用很多未导出的内核函数,怎么方便、快速查找了?可以先用IDA等工具查看硬编码,再根据硬编码定位到需要调用的函数。整个思路大致如下:

1、先查找目标模块

   遍历模块的方式有多种。既然通过驱动在内核编程,这里选择遍历driverObject的DriverSection字段来遍历内核所有模块,核心代码如下:

 /*
  可以用来动态查找内核模块的基址,后续用于:
  1、PTE\PDE等base计算
  2、其他函数、变量精确位置的计算(IDA静态分析只能查到偏移)
*/
PVOID FindMould(PDRIVER_OBJECT pDriverObject, PWCHAR moudName, PULONG pSize)
{
// 从PDRIVER_OBJECT获取DriverSection,便可获得驱动模块链表
PLDR_DATA_TABLE_ENTRY pDriverData = (PLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
// 开始遍历双向链表
PLDR_DATA_TABLE_ENTRY pFirstDriverData = pDriverData;
do
{
if (( < pDriverData->BaseDllName.Length) ||
( < pDriverData->FullDllName.Length))
{
// 显示
DbgPrint("BaseDllName=%ws,\tDllBase=0x%p,\tSizeOfImage=0x%X,\tFullDllName=%ws\n",
pDriverData->BaseDllName.Buffer, pDriverData->DllBase,
pDriverData->SizeOfImage, pDriverData->FullDllName.Buffer);
//BaseDllName.Buffer是PWCH,也就是宽字符串,所以自己定义的moudName也要是PWCHAR类型
if (!_stricmp(moudName, (PCHAR)pDriverData->BaseDllName.Buffer))
{
DbgPrint("find target : BaseDllName=%ws,\tDllBase=0x%p,\tSizeOfImage=0x%X,\tFullDllName=%ws\n",
pDriverData->BaseDllName.Buffer, pDriverData->DllBase,
pDriverData->SizeOfImage, pDriverData->FullDllName.Buffer);
*pSize = pDriverData->SizeOfImage;
return pDriverData->DllBase;
} }
// 下一个
pDriverData = (PLDR_DATA_TABLE_ENTRY)pDriverData->InLoadOrderLinks.Flink; } while (pFirstDriverData != pDriverData); return NULL;
}

  传入driverObject、模块名称,得到模块基址(返回值)和模块长度(参数);

2、得到模块基址后,再进一步根据特征码查找目标函数:

 PVOID FindFun(PVOID pSearchBeginAddr, ULONG ulSearchLength, PUCHAR pSpecialCode, ULONG ulSpecialCodeLength)
{
PVOID pDestAddr = NULL;
PUCHAR pBeginAddr = (PUCHAR)pSearchBeginAddr;
PUCHAR pEndAddr = pBeginAddr + ulSearchLength;
PUCHAR i = NULL;
ULONG j = ; for (i = pBeginAddr; i <= pEndAddr; i++)
{
// 遍历特征码
for (j = ; j < ulSpecialCodeLength; j++)
{
// 判断地址是否有效 ntoskrnl.exe有时地址无效,蓝屏报错:PAGE FAULED IN NONPAGED AREA
if (FALSE == MmIsAddressValid((PVOID)(i + j)))
{
break;
}
// 匹配特征码
if (*(PUCHAR)(i + j) != pSpecialCode[j])
{
break;
}
}
// 匹配成功
if (j >= ulSpecialCodeLength)
{
pDestAddr = (PVOID)i;
break;
}
} return pDestAddr;
}

  这里特征码搜索可以继续改进,比如用正则做模糊匹配~~~

3、用法举例:强行杀死线程时,需要调用 PspTerminateThreadByPointer 函数,但此函数并未导出,可以通过IDA查看汇编代码,也可以在windbg通过U PspTerminateThreadByPointer,如下:

kd> u nt!PspTerminateThreadByPointer

nt!PspTerminateThreadByPointer:

fffff803`d01c6210 48895c2408      mov     qword ptr [rsp+8],rbx

fffff803`d01c6215 48896c2410      mov     qword ptr [rsp+10h],rbp

fffff803`d01c621a 4889742418      mov     qword ptr [rsp+18h],rsi

fffff803`d01c621f 57              push    rdi

fffff803`d01c6220 4883ec30        sub     rsp,30h

fffff803`d01c6224 8b81d0060000    mov     eax,dword ptr [rcx+6D0h]

fffff803`d01c622a 418ae8          mov     bpl,r8b

fffff803`d01c622d 488bb920020000  mov     rdi,qword ptr [rcx+220h]

由于大多数函数刚开始都是初始化堆栈代码,这里特征码重合度较高,为了避免找到其他函数,建议从稍微靠后几行代码处提取特征码,比如这里从第7行开始提取 418ae8488bb920020000 10个字节,找到后再减去26字节就回到了PspTerminateThreadByPointer入口;

 NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
DbgPrint("Enter DriverEntry\n"); NTSTATUS status = STATUS_SUCCESS;
pDriverObject->DriverUnload = DriverUnload;
for (ULONG i = ; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
pDriverObject->MajorFunction[i] = DriverDefaultHandle;
} ULONG mouldSize = ;
PWCHAR mouldName = L"ntkrnlmp.exe";
PVOID mouldBase = FindMould(pDriverObject, mouldName, &mouldSize); DbgPrint("mould name = %ws ; mould base = 0x%p; mould size = 0x%X\n", mouldName, mouldBase, mouldSize); UCHAR pSpecialCode[] = { };
/*418ae8488bb920020000*/
pSpecialCode[] = 0x41;
pSpecialCode[] = 0x8a;
pSpecialCode[] = 0xe8;
pSpecialCode[] = 0x48;
pSpecialCode[] = 0x8b;
pSpecialCode[] = 0xb9;
pSpecialCode[] = 0x20;
pSpecialCode[] = 0x02;
pSpecialCode[] = 0x00;
pSpecialCode[] = 0x00; PVOID FunAddress = FindFun(mouldBase, mouldSize, pSpecialCode, );
DbgPrint("Finally function address = 0x%p;\n", FunAddress-); return status;
}

windows:根据特征码查找内核任意函数的更多相关文章

  1. [原创]使用GCC创建 Windows NT 下的内核DLL

    原文链接:使用GCC创建 Windows NT 下的内核DLL 在温习<<Windows 2000 Driving>>分层驱动程序一章的时候,看到了关于紧耦合驱动连接方式,这种 ...

  2. 【Windows下DLL查找顺序 】

    一.写作初衷 在Windows下单个DLL可能存在多个不同的版本,若不特别指定DLL的绝对路径或使用其他手段指定,在应用程序加载DLL时可能会查找到错误的版本,进而引出各种莫名其妙的问题.本文主要考虑 ...

  3. Delphi For Android 开发笔记-附:如何Delphi中同时实现Windows、Android版的GetModuleFileName函数

    在Windows中开发DLL时,经常会需要获取当前DLL所在目录以便读取同目录下的其他文件,而目前Delphi在开发android时,其实没多大必要获取,因为整个工程只有一个so文件,而这个so文件也 ...

  4. 在windows下解压缩Linux内核源代码出现重复文件原因

    在windows下解压缩Linux内核源代码出现重复文件原因 2009年06月30日 13:35 来源:ChinaUnix博客 作者:embededgood 编辑:周荣茂     原因一.因为在Lin ...

  5. Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)

    Qt Windows下链接子系统与入口函数(终结版) 转载自:http://blog.csdn.net/dbzhang800/article/details/6358996 能力所限,本讨论仅局限于M ...

  6. linux2.6内核compat_ioctl函数

    一.内核原型(linux2.6.28-7) long (*compat_ioctl)(struct tty_struct *tty, struct file * file,               ...

  7. Windows下DLL查找顺序

    目录 第1章说明    2 1.1 查找顺序    2 1.1.1 检查DllCharacteristics字段    3 1.1.2 读取manifset资源    3 1.1.3 读取manifs ...

  8. Linux内核d_path函数应用的经验总结

    问题背景 一个内核模块中,需要通过d_path接口获取文件的路径,然后与目标文件白名单做匹配. 在生产环境中,获取的文件是存在的,但是与文件白名单中的文件总是匹配失败. 问题定位: 通过打印d_pat ...

  9. 内核开发知识第一讲.内核中的数据类型.重要数据结构.常用内核API函数.

    一丶内核中的数据类型 在内核中.程序的编写不能简单的用基本数据类型了. 因为操作系统不同.很有可能造成数据类型的长度不一.而产生重大问题.所以在内核中. 数据类型都一定重定义了. 数据类型 重定义数据 ...

随机推荐

  1. 一篇文章教会你如何将DOM转换为virtual DOM

    [一.Virtual DOM简介] Virtual DOM是虚拟节点,它通过Javascript的Object对象模拟DOM中的节点,然后通过特定的render方法将其渲染成真实的DOM节点. 浏览器 ...

  2. 初学linux常见问题

    学习视频:<Linux从入门到精通> 1.Linux系统与我们常用的windows系统有什么相同与不同之处? 相同之处:都是操作系统,可以安装其他的软件 不同之处:从使用方式上来看,win ...

  3. 论TEMP临时变量与VAR静态变量

    TEMP临时变量:顾名思义,这种变量类型是临时的,没有固定的存放数据的内存空间.每次扫描结束后则清零,在下个扫描周期开始时,这个变量的值都是不确定的,一般为0.使用临时变量需要遵循一个原则:先赋值再使 ...

  4. 数据规整:连接、联合与重塑知识图谱-《利用Python进行数据分析》

    所有内容整理自<利用Python进行数据分析>,使用MindMaster Pro 7.3制作,emmx格式,源文件已经上传Github,需要的同学转左上角自行下载或者右击保存图片. 其他章 ...

  5. HTML学习分享(一)

    HTML学习小结(一) 1.css的全称是什么? 2.样式表的组成 3.浏览器读取编译css的顺序? (1)HTML基本选择器 1.通配符选择器 * { margin: 0; padding: 0; ...

  6. 转载一篇关于kafka零拷贝(zero-copy)通俗易懂的好文

    原文地址 https://www.cnblogs.com/yizhou35/p/12026263.html 零拷贝就是一种避免CPU 将数据从一块存储拷贝到另外一块存储的技术. DMA技术是Direc ...

  7. T133308 57级返校测试重测-T3-成绩单

    大致题意: 给定n个学生的学号和分数, 求各个分数段的人数, 求把学号排序后的序列, 求满分的人数以及学号. 基本思路: 虽然看起来很繁琐(?),但就非常非常的简单,直接按题意做就好了. 然后有个坑, ...

  8. linux : 新服务器部署项目要做的事

    环境:阿里云服务器两台,一台web,一台db,系统centos7. 用户用外网访问web server ,web server 再去访问db server. 1 阿里云控制台进入系统2 SSH进入系统 ...

  9. IOS上传图片方向问题

    在显示上传完毕的图片的时候遇到了一个问题, 图片莫名其妙被逆时针旋转了90度就很离谱 如下图 经过一番查询, 原来是 IOS 的相机拍照的时候会把方向角写入到图片里面 因为我用的是 element 的 ...

  10. html命名规则

    CSS样式命名 外套 wrap ------------------用于最外层 头部 header ----------------用于头部 主要内容 main ------------用于主体内容( ...