首页
社区
课程
招聘
[原创]为你的驱动挂上外挂 - 嵌入反汇编引擎
发表于: 2011-9-25 22:11 49155

[原创]为你的驱动挂上外挂 - 嵌入反汇编引擎

2011-9-25 22:11
49155


首先来看两段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;


原版的OD引擎将指令类型定义为了UCHAR,限制了指令的细分数量,大家可以根据需要自己调整一下,
因为自己这样已经够用了,也就没有扩展

另外主函数和返回结构也进行了消减:
typedef struct _Disasm {
	ULONG  cmdtype;   //指令类型
	ULONG  error;         //错误信息
	ULONG  warnings;  //警告信息
}Disasm,*PDisasm;

ULONG DisasmCode(PUCHAR Src,ULONG SrcSize,PDisasm pDisasm);

Src:要反汇编的指令地址
SrcSize:指令长度
pDisasm:返回结构


使用上是与原版的OD相同的

************************************************
************************************************
测试的时候写了一个小程序,效果如下:
输入指定函数名称和反汇编长度:


通过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);

头文件只引用disasm.h即可

#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;
}


解析指令时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

[课程]Android-CTF解题方法汇总!

上传的附件:
收藏
免费 7
支持
分享
最新回复 (72)
雪    币: 535
活跃值: (245)
能力值: ( LV12,RANK:400 )
在线值:
发帖
回帖
粉丝
2
自己占楼备用
2011-9-25 22:11
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
3
很好的帖子啊,被我第一个看到了
2011-9-25 22:33
0
雪    币: 149
活跃值: (126)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
我也看到了。先占楼再围观。
2011-9-25 23:43
0
雪    币: 402
活跃值: (342)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
5
lasm简单的修改下貌似就能达到LZ的要求吧,用不了17k
2011-9-26 01:28
0
雪    币: 191
活跃值: (1978)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
不错收藏一份了
2011-9-26 01:59
0
雪    币: 242
活跃值: (418)
能力值: ( LV11,RANK:188 )
在线值:
发帖
回帖
粉丝
7
很帅,支持sky大侠
我想提下建议,论坛现在的代码格式的字体太小了啊,用引用会不会好些?
一般定位特征码,lde也很好用的
2011-9-26 02:32
0
雪    币: 7035
活跃值: (4184)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
强大,楼主每帖必复
2011-9-26 07:32
0
雪    币: 768
活跃值: (515)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
9
新鲜,~收藏备用:)
2011-9-26 08:02
0
雪    币: 1015
活跃值: (235)
能力值: ( LV12,RANK:440 )
在线值:
发帖
回帖
粉丝
10
支持一个
2011-9-26 08:10
0
雪    币: 2
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
很详细的,支持一个!
2011-9-26 10:06
0
雪    币: 435
活跃值: (1207)
能力值: ( LV13,RANK:388 )
在线值:
发帖
回帖
粉丝
12
谢谢 下载收藏
2011-9-26 10:20
0
雪    币: 170
活跃值: (90)
能力值: ( LV12,RANK:210 )
在线值:
发帖
回帖
粉丝
13
厉害啊 下载一份
2011-9-26 13:56
0
雪    币: 4580
活跃值: (992)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
14
灰常好,收藏一份
2011-9-26 14:08
0
雪    币: 375
活跃值: (12)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
15
用udis86吧。
2011-9-26 15:08
0
雪    币: 110
活跃值: (14)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
不错,支持!
2011-9-26 16:28
0
雪    币: 210
活跃值: (221)
能力值: ( LV9,RANK:180 )
在线值:
发帖
回帖
粉丝
17
挺好的、、、、、虽然傻傻的只懂一点
2011-9-26 22:46
0
雪    币: 2503
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
不错 学习学习 看看!!!
2011-9-26 23:18
0
雪    币: 322
活跃值: (113)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
属于喜欢的类型
2011-9-26 23:57
0
雪    币: 71
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
很好,很强大
thisis很厉害
2011-9-27 00:13
0
雪    币: 563
活跃值: (95)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
mark谢谢!!
2011-9-27 00:22
0
雪    币: 1683
活跃值: (674)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
22
收藏,备用。。。
2011-9-27 07:41
0
雪    币: 492
活跃值: (53)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
23
好东西,收藏了
2011-9-27 11:28
0
雪    币: 962
活跃值: (1681)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
这个确实不错
2011-9-27 12:00
0
雪    币: 410
活跃值: (214)
能力值: ( LV13,RANK:220 )
在线值:
发帖
回帖
粉丝
25
mark下,还不错
2011-9-27 14:45
0
游客
登录 | 注册 方可回帖
返回
//