首页
论坛
专栏
课程

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

2011-9-25 22:11 45215

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

2011-9-25 22:11
45215


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


[公告]安全测试和项目外包请将项目需求发到看雪企服平台:https://qifu.kanxue.com

上传的附件:
最新回复 (72)
thisIs 9 2011-9-25 22:11
2
0
自己占楼备用
tihty 3 2011-9-25 22:33
3
0
很好的帖子啊,被我第一个看到了
robey 1 2011-9-25 23:43
4
0
我也看到了。先占楼再围观。
ProgmBoy 3 2011-9-26 01:28
5
0
lasm简单的修改下貌似就能达到LZ的要求吧,用不了17k
freecat 1 2011-9-26 01:59
6
0
不错收藏一份了
XPoy 3 2011-9-26 02:32
7
0
很帅,支持sky大侠
我想提下建议,论坛现在的代码格式的字体太小了啊,用引用会不会好些?
一般定位特征码,lde也很好用的
nekaxi 2011-9-26 07:32
8
0
强大,楼主每帖必复
FishSeeWater 11 2011-9-26 08:02
9
0
新鲜,~收藏备用:)
loongzyd 10 2011-9-26 08:10
10
0
支持一个
benjork 2011-9-26 10:06
11
0
很详细的,支持一个!
bitt 5 2011-9-26 10:20
12
0
谢谢 下载收藏
竹君 5 2011-9-26 13:56
13
0
厉害啊 下载一份
b23526 2011-9-26 14:08
14
0
灰常好,收藏一份
xPLK 3 2011-9-26 15:08
15
0
用udis86吧。
Elele 2011-9-26 16:28
16
0
不错,支持!
kwting 3 2011-9-26 22:46
17
0
挺好的、、、、、虽然傻傻的只懂一点
淡定是罪 2011-9-26 23:18
18
0
不错 学习学习 看看!!!
高军 2011-9-26 23:57
19
0
属于喜欢的类型
mumaren 2011-9-27 00:13
20
0
很好,很强大
thisis很厉害
lixupeng 2011-9-27 00:22
21
0
mark谢谢!!
djxh 2011-9-27 07:41
22
0
收藏,备用。。。
fhurricane 1 2011-9-27 11:28
23
0
好东西,收藏了
loqich 2011-9-27 12:00
24
0
这个确实不错
zyhfut 5 2011-9-27 14:45
25
0
mark下,还不错
guazi 2011-9-27 18:47
26
0
看懂一点了,还要继续努力
Nermor 1 2011-9-27 19:05
27
0
这思路 不错 , 哈哈
选择 2011-9-28 12:57
28
0
有创意。收藏了。
dlmu 1 2011-9-28 13:11
29
0
哇塞,赶紧收藏一份
jerrynpc 2011-9-28 14:57
30
0
。。。。。。。。。。。。zzz 这东西没啥用吧
MengXP 2011-9-28 17:31
31
0
LDE才1KB啊。。
achillis 15 2011-9-28 20:26
32
0
LDE有时会出错啊
justlovemm 2011-9-29 10:25
33
0
mark一下,方便以后查找。
多谢楼主分享。
zuoyefeng 2011-9-29 16:10
34
0
markkkkkkk
zuoyefeng 2011-9-29 16:11
35
0
话说大家都是那么直接的用引擎的时候,咱们就不能这么直接的用鸟
不就是想检测不到偶们的hook么~~~~
还要xxx才行啊
hkwind 2011-9-30 17:08
36
0
mark一下,方便以后查找。
多谢楼主分享。
tianzun 2011-10-9 16:16
37
0
谢谢 下载收藏
mgsz 2011-10-11 21:30
38
0
收藏一下,收藏一下
jasonnbfan 8 2012-3-24 12:15
39
0
不错记录下。
gogogo911 2012-3-29 21:30
40
0
都是牛人
wulongxian 2012-4-4 21:41
41
0
很详细的,支持
ndayo 2012-4-13 01:20
42
0
收藏了  ,很快就要用上了 ,谢谢lz
ugvjewxf 2012-4-18 10:28
43
0
好文,顶起,再看,
yuweiping 2012-4-22 09:36
44
0
悄悄的问个问题,我也mark这个这个文章,但是我不知道以后就可以直接找到我MARK过的文章呢?
moonspot 2012-4-22 16:01
45
0
标记一下收藏
gezz 2012-4-27 17:37
46
0
好贴要顶一个啊!反汇编引擎一直都在找个合适的~
lhwqqq 2012-5-24 21:17
47
0
好腻害啊 佩服佩服
圜长 2012-6-14 15:10
48
0
很实用的东西,偷偷下下来研究下
bbzhu 2012-6-24 23:17
49
0
新鲜的东西,占楼备用!
egodcore 2012-6-26 22:07
50
0
目测 最近avg反了一个这种反汇编的木马
游客
登录 | 注册 方可回帖
返回