首页
社区
课程
招聘
[求助]关于SYS加载DLL
发表于: 2010-10-18 16:02 6736

[求助]关于SYS加载DLL

2010-10-18 16:02
6736
本人刚刚学习驱动,想根据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作者讲授!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 253
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
2
请各位大虾赐教,因为刚开始学习驱动,所以很多问题搞不明白~标红的那一行就是windbg提示错误的地方。
2010-10-18 21:43
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
3
CR0的那些操作完全无必要
MapViewOfSection时的PAGE_READWRITE要用EXEC+READ+WRITE
2010-10-19 19:01
0
雪    币: 253
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
4
感谢V大。我加了Execute权限,还是会蓝屏。还是那句往缝隙里拷贝的memcpy蓝的,感觉好像不能往里面写。
还有一个问题就是,为什么连着windbg就没有问题,单独运行就有问题?
2010-10-21 10:01
0
雪    币: 37
活跃值: (25)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
还有一个问题就是,为什么连着windbg就没有问题,单独运行就有问题?
一般这种情况 不管什么代码 我总想到 1 CHECK 2 FREE  3  ASM INT 3  这三个设置组合设置对没
2010-10-21 12:50
0
雪    币: 253
活跃值: (46)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
6
嗯,我也想到过,应该不是那些问题。 应该就是不能往里面写,不过连着windbg的时候就可以写!不清楚是为什么。
2010-10-21 15:13
0
游客
登录 | 注册 方可回帖
返回
//