|
标 题:
【原创】为你的驱动挂上外挂 - 嵌入反汇编引擎
作 者: thisIs
时 间: 2011-09-25,22:11:03
链 接: http://bbs.pediy.com/showthread.php?t=140587
首先来看两段IDA中的代码
上面的图是win xp下 NtOpenProcess 中的代码片段
下面的图是win 7下 PsOpenProcess 中的代码片段,win 7中 NtOpenProcess 成了包装函数,由PsOpenProcess真正完成打开进程的操作
两个系统中打开某一进程时的指令执行路径上都会经过ObOpenObjectByPointer函数,
该函数在这里传进进程的EPROCESS结构,返回相应的进程句柄,该句柄最终返回给我们
可见如果在这里inline hook了ObOpenObjectByPointer函数,并通过比对EPROCESS来过滤自身的话,
就能防止被其他进程打开访问自己的进程
那么我们如果想修复这个inline hook的话,首先想到的方法就是定位到hook的指令处,
然后通过取得真实的ObOpenObjectByPointer函数地址来进行修复
但是,这条指令位于函数比较深层的位置,在函数头500+以后的偏移地址,如果用通常的搜索特征码的方式进行定位难度比较大,
而且也不容易做到多系统兼容:xp下的ObOpenObjectByPointer前后的指令与win7下ObOpenObjectByPointer前后的指令长度并不相符,
当然你可以选择针对不同的系统,使用多套特征码进行搜寻定位,但这与反汇编引擎比起来通用性,安全性都不在一个级别
前段时间一直在想找个比较小巧的反汇编引擎,我的要求比较简单,能测出指令长度和指令类型就行,
不过找了几个都不理想<也可能自己愚笨,没搞懂怎么使用>
以前在RING3层的时候一直在使用OD的反汇编引擎,不过把OD的上百KB的引擎嵌入我区区几十KB的驱动有点喧宾夺主了,
于是自己花了点时间精简了一下OD的反汇编引擎,效果上还算比较理想
精简之后去掉了所有字串相关操作,也就是将不会有字串形式的参考信息;
指令表那里去掉了C_NOW,C_MMX,C_FLT这样至少我用不着的指令,如果大家需要的话可以自己添加上;
定义了一组指令类型,基本包含了所有的常见指令,当然大家也是可以自己进行添加的.
需要注意的只有这里:
原版的OD引擎将指令类型定义为了UCHAR,限制了指令的细分数量,大家可以根据需要自己调整一下,
因为自己这样已经够用了,也就没有扩展
另外主函数和返回结构也进行了消减:
使用上是与原版的OD相同的
************************************************
************************************************
测试的时候写了一个小程序,效果如下:
输入指定函数名称和反汇编长度:
通过DebugView可以看到反汇编的结果<指令类型+指令长度>:
与livekd对比一下,没有异常:
下面简单说一下使用方法,应用层就不在这里讨论了,只看一下驱动方面:
头文件只引用disasm.h即可
解析指令时dw将返回被解析的字节长度,正常情况下也就是一条指令的长度,
DecodedLength用来累加已被解析的长度
这只是最简单的一个小应用,如何让它在驱动中发挥更大的作用全在你的想象力~~
想想前面的搜索调用ObOpenObjectByPointer的指令地址,使用反汇编引擎可以很容易得实现
精简之后checked编译这个驱动大小为17KB,还是能接受的
由于水平所限,难免出现BUG,如果各位朋友在使用过程中发现了什么问题,请一定要告诉我啊~
我的QQ:2575439022
下面附上精简的OD反汇编引擎源文件,另外我也写了一份delphi版本的精简引擎,方便喜欢用delphi的朋友,一并上传了.
C精简版 : DisAsm_Mini_C.rar
DELPHI精简版 : DisAsm_Mini_delphi.rar
C原版 : DisAsm_C.rar
DELPHI原版修改版<适用UNICODE编码> : DisAsm_delphi.rar
作 者: thisIs
时 间: 2011-09-25,22:11:03
链 接: http://bbs.pediy.com/showthread.php?t=140587
首先来看两段IDA中的代码
上面的图是win xp下 NtOpenProcess 中的代码片段
下面的图是win 7下 PsOpenProcess 中的代码片段,win 7中 NtOpenProcess 成了包装函数,由PsOpenProcess真正完成打开进程的操作
两个系统中打开某一进程时的指令执行路径上都会经过ObOpenObjectByPointer函数,
该函数在这里传进进程的EPROCESS结构,返回相应的进程句柄,该句柄最终返回给我们
可见如果在这里inline hook了ObOpenObjectByPointer函数,并通过比对EPROCESS来过滤自身的话,
就能防止被其他进程打开访问自己的进程
那么我们如果想修复这个inline hook的话,首先想到的方法就是定位到hook的指令处,
然后通过取得真实的ObOpenObjectByPointer函数地址来进行修复
但是,这条指令位于函数比较深层的位置,在函数头500+以后的偏移地址,如果用通常的搜索特征码的方式进行定位难度比较大,
而且也不容易做到多系统兼容:xp下的ObOpenObjectByPointer前后的指令与win7下ObOpenObjectByPointer前后的指令长度并不相符,
当然你可以选择针对不同的系统,使用多套特征码进行搜寻定位,但这与反汇编引擎比起来通用性,安全性都不在一个级别
前段时间一直在想找个比较小巧的反汇编引擎,我的要求比较简单,能测出指令长度和指令类型就行,
不过找了几个都不理想<也可能自己愚笨,没搞懂怎么使用>
以前在RING3层的时候一直在使用OD的反汇编引擎,不过把OD的上百KB的引擎嵌入我区区几十KB的驱动有点喧宾夺主了,
于是自己花了点时间精简了一下OD的反汇编引擎,效果上还算比较理想
精简之后去掉了所有字串相关操作,也就是将不会有字串形式的参考信息;
指令表那里去掉了C_NOW,C_MMX,C_FLT这样至少我用不着的指令,如果大家需要的话可以自己添加上;
定义了一组指令类型,基本包含了所有的常见指令,当然大家也是可以自己进行添加的.
需要注意的只有这里:
代码:
typedef struct _CmdData { ULONG mask; ULONG code; UCHAR len; UCHAR bits; UCHAR arg1,arg2,arg3; UCHAR type; //指令类型 }CmdData, *PCmdData;
因为自己这样已经够用了,也就没有扩展
另外主函数和返回结构也进行了消减:
代码:
typedef struct _Disasm { ULONG cmdtype; //指令类型 ULONG error; //错误信息 ULONG warnings; //警告信息 }Disasm,*PDisasm; ULONG DisasmCode(PUCHAR Src,ULONG SrcSize,PDisasm pDisasm); Src:要反汇编的指令地址 SrcSize:指令长度 pDisasm:返回结构
************************************************
************************************************
测试的时候写了一个小程序,效果如下:
输入指定函数名称和反汇编长度:
通过DebugView可以看到反汇编的结果<指令类型+指令长度>:
与livekd对比一下,没有异常:
下面简单说一下使用方法,应用层就不在这里讨论了,只看一下驱动方面:
代码:
#ifndef DISASMMAIN_H #define DISASMMAIN_H #endif #include <ntddk.h> #include "disasm.h" //与RING3层通讯结构 typedef struct _myStruct{ ULONG Length; //反汇编长度 PWCHAR pFuncName[100]; //要反汇编的函数名称 }myStruct,*PMyStruct; DRIVER_INITIALIZE DriverEntry; NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath); __drv_dispatchType(IRP_MJ_DEVICE_CONTROL) DRIVER_DISPATCH DispatchDeviceIoControl; NTSTATUS DispatchDeviceIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); __drv_dispatchType_other DRIVER_DISPATCH DispatchCompletion; NTSTATUS DispatchCompletion(PDEVICE_OBJECT pDeviceObject, PIRP pIrp); DRIVER_UNLOAD Unload; VOID Unload(PDRIVER_OBJECT pDriverObject);
代码:
#include "disAsmMain.h" #pragma alloc_text (INIT,DriverEntry) #pragma alloc_text (PAGE,DispatchDeviceIoControl) #pragma alloc_text (PAGE,Unload) #pragma alloc_text (PAGE,DispatchCompletion) #define DEVICE_NAME L"\\Device\\disAsm" #define DEVICE_SYMBOLICLINK_NAME L"\\DosDevices\\disAsmSymLink" #define IOCTL_DISASM_SPECIAL_FUNCTION (CTL_CODE(FILE_DEVICE_UNKNOWN,0x801,FILE_ANY_ACCESS,METHOD_BUFFERED)) NTSTATUS DispatchDeviceIoControl(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { ULONG ulIoControlCode; //控制代码 PVOID pvBuf = NULL; PIO_STACK_LOCATION pIrpStatck = NULL; NTSTATUS status = STATUS_UNSUCCESSFUL; PMyStruct pFuncInfo; PVOID pFuncAddress = NULL; UNICODE_STRING destString; ULONG DecodedLength = 0; ULONG dw; Disasm dis; pIrpStatck = IoGetCurrentIrpStackLocation(pIrp); ulIoControlCode = pIrpStatck->Parameters.DeviceIoControl.IoControlCode; pvBuf = pIrp->AssociatedIrp.SystemBuffer; pIrp->IoStatus.Status = status; pIrp->IoStatus.Information = 0; pFuncInfo = (PMyStruct)pvBuf; KdPrint(("目标函数:%S",(PWCHAR)pFuncInfo->pFuncName)); switch ( ulIoControlCode ) { case IOCTL_DISASM_SPECIAL_FUNCTION: if ( pFuncInfo->Length == 0 ) break; RtlInitUnicodeString(&destString,(PWCHAR)pFuncInfo->pFuncName); pFuncAddress = MmGetSystemRoutineAddress(&destString); if (pFuncAddress == NULL) { KdPrint(("未发现指定函数")); break; } while ( DecodedLength < pFuncInfo->Length ) { dw = DisasmCode((PUCHAR)((ULONG)pFuncAddress+DecodedLength),pFuncInfo->Length - DecodedLength,&dis); DecodedLength = DecodedLength + dw; switch ( dis.cmdtype ) { case C_NOP: KdPrint(("C_NOP %d",dw)); break; case C_TST: KdPrint(("C_TST %d",dw)); break; case C_CMP: KdPrint(("C_CMP %d",dw)); break; case C_CMPS: KdPrint(("C_CMPS %d",dw)); break; case C_CMPSB: KdPrint(("C_CMPSB %d",dw)); break; case C_CMPSW: KdPrint(("C_CMPSW %d",dw)); break; case C_CMPSD: KdPrint(("C_CMPSD %d",dw)); break; case C_MOV: KdPrint(("C_MOV %d",dw)); break; case C_MOVS: KdPrint(("C_MOVS %d",dw)); break; case C_MOVSX: KdPrint(("C_MOVSX %d",dw)); break; case C_MOVSB: KdPrint(("C_MOVSB %d",dw)); break; case C_MOVSW: KdPrint(("C_MOVSW %d",dw)); break; case C_MOVSD: KdPrint(("C_MOVSD %d",dw)); break; case C_MOVZX: KdPrint(("C_MOVZX %d",dw)); break; case C_JMP: KdPrint(("C_JMP %d",dw)); break; case C_JMC: KdPrint(("C_JMC %d",dw)); break; case C_CAL: KdPrint(("C_CAL %d",dw)); break; case C_RET: KdPrint(("C_RET %d",dw)); break; case C_XOR: KdPrint(("C_XOR %d",dw)); break; case C_AND: KdPrint(("C_AND %d",dw)); break; case C_OR: KdPrint(("C_OR %d",dw)); break; case C_NOT: KdPrint(("C_NOT %d",dw)); break; case C_PSH: KdPrint(("C_PSH %d",dw)); break; case C_POP: KdPrint(("C_POP %d",dw)); break; case C_PSHA: KdPrint(("C_PSHA %d",dw)); break; case C_POPA: KdPrint(("C_POPA %d",dw)); break; case C_PSHF: KdPrint(("C_PSHF %d",dw)); break; case C_POPF: KdPrint(("C_POPF %d",dw)); break; case C_ADD: KdPrint(("C_ADD %d",dw)); break; case C_ADC: KdPrint(("C_ADC %d",dw)); break; case C_SBB: KdPrint(("C_SBB %d",dw)); break; case C_SUB: KdPrint(("C_SUB %d",dw)); break; case C_INC: KdPrint(("C_INC %d",dw)); break; case C_DEC: KdPrint(("C_DEC %d",dw)); break; case C_MUL: KdPrint(("C_MUL %d",dw)); break; case C_IMUL: KdPrint(("C_IMUL %d",dw)); break; case C_DIV: KdPrint(("C_DIV %d",dw)); break; case C_IDIV: KdPrint(("C_IDIV %d",dw)); break; case C_NEG: KdPrint(("C_NEG %d",dw)); break; case C_LEA: KdPrint(("C_LEA %d",dw)); break; case C_XCHG: KdPrint(("C_XCHG %d",dw)); break; case C_SHR: KdPrint(("C_SHR %d",dw)); break; case C_SHL: KdPrint(("C_SHL %d",dw)); break; case C_ROL: KdPrint(("C_ROL %d",dw)); break; case C_ROR: KdPrint(("C_ROR %d",dw)); break; case C_RCL: KdPrint(("C_RCL %d",dw)); break; case C_RCR: KdPrint(("C_RCR %d",dw)); break; case C_SAR: KdPrint(("C_SAR %d",dw)); break; case C_SAL: KdPrint(("C_SAK %d",dw)); break; case C_CLI: KdPrint(("C_CLI %d",dw)); break; case C_STI: KdPrint(("C_STI %d",dw)); break; case C_ENTER: KdPrint(("C_ENTER %d",dw)); break; case C_LEAVE: KdPrint(("C_LEAVE %d",dw)); break; case C_INT: KdPrint(("C_INT %d",dw)); break; case C_INT3: KdPrint(("C_INT3 %d",dw)); break; case C_SYSENTER: KdPrint(("C_SYSENTER %d",dw)); break; case C_SYSEXIT: KdPrint(("C_SYSEXIT %d",dw)); break; default: KdPrint(("C_UNKNOW %d",dw)); break; } } pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status = STATUS_SUCCESS; KdPrint(("打完收工")); break; default: KdPrint(("接收到非法命令\n")); pIrp->IoStatus.Information = 0; pIrp->IoStatus.Status = status = STATUS_INVALID_DEVICE_REQUEST; break; } IoCompleteRequest(pIrp,IO_NO_INCREMENT); return status; } VOID Unload(PDRIVER_OBJECT pDriverObject) { UNICODE_STRING SymLinkName; RtlInitUnicodeString(&SymLinkName,DEVICE_SYMBOLICLINK_NAME); IoDeleteSymbolicLink(&SymLinkName); IoDeleteDevice(pDriverObject->DeviceObject); } NTSTATUS DispatchCompletion(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) { pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = 0; IoCompleteRequest(pIrp,IO_NO_INCREMENT); return STATUS_SUCCESS; } DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) { PDEVICE_OBJECT pMyDeviceObject = NULL; UNICODE_STRING SymLinkName; UNICODE_STRING MyDeviceName; NTSTATUS status = STATUS_SUCCESS; ULONG i; for(i=0; i<IRP_MJ_MAXIMUM_FUNCTION; i++) pDriverObject->MajorFunction[i] = DispatchCompletion; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceIoControl; pDriverObject->DriverUnload = Unload; //创建设备对象 RtlInitUnicodeString(&MyDeviceName,DEVICE_NAME); status = IoCreateDevice(pDriverObject,0,&MyDeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&pMyDeviceObject); if (!NT_SUCCESS(status)){ KdPrint(("创建设备对象失败\n")); return status; } //创建符号链接 RtlInitUnicodeString(&SymLinkName,DEVICE_SYMBOLICLINK_NAME); status = IoCreateSymbolicLink(&SymLinkName,&MyDeviceName); if (!NT_SUCCESS(status)){ IoDeleteDevice(pMyDeviceObject); KdPrint(("创建符号链接失败\n")); return status; } pMyDeviceObject->Flags |= DO_BUFFERED_IO; pMyDeviceObject->Flags = pMyDeviceObject->Flags & ~ DO_DEVICE_INITIALIZING; return status; }
DecodedLength用来累加已被解析的长度
这只是最简单的一个小应用,如何让它在驱动中发挥更大的作用全在你的想象力~~
想想前面的搜索调用ObOpenObjectByPointer的指令地址,使用反汇编引擎可以很容易得实现
精简之后checked编译这个驱动大小为17KB,还是能接受的
由于水平所限,难免出现BUG,如果各位朋友在使用过程中发现了什么问题,请一定要告诉我啊~
我的QQ:2575439022
下面附上精简的OD反汇编引擎源文件,另外我也写了一份delphi版本的精简引擎,方便喜欢用delphi的朋友,一并上传了.
C精简版 : DisAsm_Mini_C.rar
DELPHI精简版 : DisAsm_Mini_delphi.rar
C原版 : DisAsm_C.rar
DELPHI原版修改版<适用UNICODE编码> : DisAsm_delphi.rar