xiaoc1026 发表于 2013-6-7 20:42:02

求助拦截DLL加载问题

我在 PsSetLoadImageNotifyRoutine 中拦截DLL的加载,修改PIAMGE_INFO 镜像入口地址总是不成功,直接RtlCopyMemory pEntryPoint 前5个字节就蓝屏,使用MDL 修改无效果,没办法,求大虾们指点一下!

Tesla.Angela 发表于 2013-6-7 23:03:02

随便贴一段我原创的禁止加载DLL的代码给你,最早是为WIN64AST所写的,你要用的话需要稍微修改一下代码,记得要在SystemThread里执行。void DenyLoadDll(PSIZE_T data)
{
        PEPROCESS dld_ep=(PEPROCESS)(data);
        PVOID DriverEntry=(PVOID)(data);
        UCHAR fuck64[]="\xB8\x00\x00\x00\x00\xC3";
        UCHAR fuck32[]="\xB8\x00\x00\x00\x00\xC2\x08\x00";
        PVOID BaseAddress=DriverEntry;
        ULONG OldProtect;
        SIZE_T RegionSize;
        NTSTATUS st;
        KAPC_STATE ks={0};
        if((ULONG64)DriverEntry<(ULONG64)0x7FFFFFFF)
        {
                RegionSize=sizeof(fuck32);
        }
        else
        {
                RegionSize=sizeof(fuck64);
        }
        KeStackAttachProcess(dld_ep,&ks);
        st=NtProtectVirtualMemory((HANDLE)-1,&BaseAddress,&RegionSize,PAGE_EXECUTE_READWRITE,&OldProtect);
        if(NT_SUCCESS(st))
        {
                __try
                {
                        if((ULONG64)DriverEntry<(ULONG64)0x7FFFFFFF)
                        {
                                memcpy(DriverEntry,fuck32,sizeof(fuck32));
                        }
                        else
                        {
                                memcpy(DriverEntry,fuck64,sizeof(fuck64));
                        }
                }
                __except(1)
                {
                        ;
                }
        }
        KeUnstackDetachProcess(&ks);
        PsTerminateSystemThread(STATUS_SUCCESS);
}

xiaoc1026 发表于 2013-6-8 11:34:41

Tesla.Angela 发表于 2013-6-7 23:03 static/image/common/back.gif
随便贴一段我原创的禁止加载DLL的代码给你,最早是为WIN64AST所写的,你要用的话需要稍微修改一下代码,记 ...

问下代码中的 NtProtectVirtualMemory 使用
MmGetSystemRoutineAddress 获取到的是0X00000000,方法不对吗?

Tesla.Angela 发表于 2013-6-8 19:47:32

xiaoc1026 发表于 2013-6-8 11:34 static/image/common/back.gif
问下代码中的 NtProtectVirtualMemory 使用
MmGetSystemRoutineAddress 获取到的是0X00000000,方法不对 ...

NtProtectVirtualMemory的地址不能直接用MmGetSystemRoutineAddress获得,要从SSDT里取得。

如果你不懂如何从SSDT里取NT系列函数地址,那我就无话可说了。

xiaoc1026 发表于 2013-6-9 09:57:41

Tesla.Angela 发表于 2013-6-8 19:47 static/image/common/back.gif
NtProtectVirtualMemory的地址不能直接用MmGetSystemRoutineAddress获得,要从SSDT里取得。

如果你不懂 ...

SSDT……,那在X64上就不兼容了。

xiaoc1026 发表于 2013-6-9 09:58:25

Tesla.Angela 发表于 2013-6-8 19:47 static/image/common/back.gif
NtProtectVirtualMemory的地址不能直接用MmGetSystemRoutineAddress获得,要从SSDT里取得。

如果你不懂 ...

这个地方不能用MDL 来修改的吗?我修改的好像无效果,不知道是不是不能用MDL 修改?

Tesla.Angela 发表于 2013-6-9 15:37:48

xiaoc1026 发表于 2013-6-9 09:57 static/image/common/back.gif
SSDT……,那在X64上就不兼容了。

不兼容个毛。
我是叫你从SSDT取地址,不是叫你HOOK SSDT。

Tesla.Angela 发表于 2013-6-9 15:38:13

xiaoc1026 发表于 2013-6-9 09:58 static/image/common/back.gif
这个地方不能用MDL 来修改的吗?我修改的好像无效果,不知道是不是不能用MDL 修改? ...

这个是R3的内存,貌似不能用MDL来修改。

xiaoc1026 发表于 2013-6-9 17:19:20


PVOID RetrieveFuncAddrInSSDT(IN CHAR FuncName[])
{
        PVOIDFuncAddr=NULL;
        ULONGServiceID=0;
        PSYSTEM_SERVICE_TABLE pTable = NULL;

#if defined(_WIN64)
        pTable = (PSYSTEM_SERVICE_TABLE)GetKeServiceDescriptorTable64();
#else
        pTable = &KeServiceDescriptorTable;
#endif

        if(FuncName==NULL)
        {
                return NULL;
        }
        if(FindFuncInfoInNtdll(FuncName,&ServiceID)!=NULL)
        {
                FuncAddr=*(PULONG*)((PUCHAR)pTable->ServiceTableBase+4*ServiceID);
        }
        return FuncAddr;
}

PVOID FindFuncInfoInNtdll(IN CHAR FuncName[],IN PULONG ServiceID)
{
        NTSTATUS                                        Status = STATUS_SUCCESS;
        ULONG                                          ulModuleNum,ulLen,ulRetLen;
        PSYSTEM_MODULE_INFORMATION                        SystemModuleInfo = NULL;
        PVOID                                          Buffer=0;
        ULONG                                          ulIndex=0;   
        PVOID                                          FuncAddr=NULL;

        if (FuncName==NULL || ServiceID==NULL)
        {
                return NULL;
        }

        *ServiceID=0;

        ZwQuerySystemInformation(SystemModuleInformation,NULL,0,&ulLen);
        Buffer=ExAllocatePoolWithTag(NonPagedPool,ulLen,'_Hi_');
        if (Buffer==NULL)
        {
                return NULL;
        }
        Status=ZwQuerySystemInformation(SystemModuleInformation,Buffer,ulLen,&ulRetLen);
        if (!NT_SUCCESS(Status))
        {
                return NULL;
        }
        SystemModuleInfo=(PSYSTEM_MODULE_INFORMATION)((PULONG)Buffer+1);
        ulModuleNum=*(PULONG)Buffer;
        for (ulIndex=0;ulIndex<ulModuleNum;ulIndex++)
        {
                PCHAR    CurModuleName=CurModuleName=SystemModuleInfo->ImageName + SystemModuleInfo->ModuleNameOffset;
                if(_stricmp(CurModuleName,"ntdll.dll")==0)
                {
                        PVOID    ModuleAddr=SystemModuleInfo->Base;      
                        ulIndex=ulModuleNum;

                        {
                                PIMAGE_DOS_HEADER      ImgDosHdr=NULL;
                                PIMAGE_NT_HEADERS      ImgNtHdrs=NULL;
                                PIMAGE_EXPORT_DIRECTORY ImgExpDir=NULL;

                                ImgDosHdr=(PIMAGE_DOS_HEADER)ModuleAddr;
                                ImgNtHdrs=(PIMAGE_NT_HEADERS)(ImgDosHdr->e_lfanew+(PUCHAR)ModuleAddr);
                                ImgExpDir=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)ModuleAddr+ImgNtHdrs->OptionalHeader.DataDirectory.VirtualAddress);

                                {
                                        ULONG    ulIndex;   
                                        ULONG    *ulFuncNameRVA=(ULONG    *)((PUCHAR)ModuleAddr+ImgExpDir->AddressOfNames);
                                        ULONG    *ulFuncAddrRVA=(ULONG    *)((PUCHAR)ModuleAddr+ImgExpDir->AddressOfFunctions);
                                        USHORT    *usFuncOrdiRVA=(USHORT    *)((PUCHAR)ModuleAddr+ImgExpDir->AddressOfNameOrdinals);
                                        UCHAR    *ExpFuncNmae=NULL;
                                        for (ulIndex=0;ulIndex<ImgExpDir->NumberOfNames ;ulIndex++)
                                        {
                                                ExpFuncNmae=(PUCHAR)ModuleAddr+ulFuncNameRVA;
                                                if(_stricmp(ExpFuncNmae,FuncName)==0)
                                                {
                                                        FuncAddr=(PVOID)((PUCHAR)ModuleAddr+ulFuncAddrRVA]);
                                                        *ServiceID=*(PULONG)((PUCHAR)FuncAddr+1);
                                                        ulIndex=ImgExpDir->NumberOfNames;
                                                }                  
                                        }
                                }
                        }
                }      
                else
                {
                        SystemModuleInfo++;
                }      
        }
        ExFreePoolWithTag(Buffer,'_Hi_');
        return FuncAddr;
}

VOID DenyLoadDll(PVOID pParam)
{
        PDenyLoadDllParam pContext = NULL;
        UCHAR fuck64[]="\xB8\x00\x00\x00\x00\xC3";
        UCHAR fuck32[]="\xB8\x00\x00\x00\x00\xC2\x08\x00";
        PEPROCESS pEprocess = NULL;
        KAPC_STATE ks = {0};
        SIZE_T RegionSize;
        PIMAGE_DOS_HEADER dos = NULL;
        PIMAGE_NT_HEADERS nth = NULL;
        PIMAGE_OPTIONAL_HEADER poh = NULL;
        PVOID pOEP = NULL;
        PVOID pImageBase = NULL;
        NTSTATUS status;
        PVOID BaseAddress = NULL;
        ULONG OldProtect;

        do
        {
                if( !pParam )
                {
                        break;
                }

                pContext = (PDenyLoadDllParam)pParam;

                if( pContext->hProcessId == NULL || !pContext->pImageInfo )
                {
                        break;
                }

                if( !NT_SUCCESS(PsLookupProcessByProcessId( pContext->hProcessId, &pEprocess )) )
                {
                        break;
                }

                if( !NtProtectVirtualMemory )
                {
                        NtProtectVirtualMemory = (NtProtectVirtualMemory_)RetrieveFuncAddrInSSDT("NtProtectVirtualMemory");
                }

                if( !NtProtectVirtualMemory )
                {
                        break;
                }

                //attach the process
                KeStackAttachProcess(pEprocess, &ks);

                pImageBase = pContext->pImageInfo->ImageBase;

                dos = (PIMAGE_DOS_HEADER) pImageBase;
                nth = (PIMAGE_NT_HEADERS) (dos->e_lfanew + (char *)pImageBase);
                poh = (PIMAGE_OPTIONAL_HEADER) &nth->OptionalHeader;

                // "MZ" "PE\0\0"
                if( (dos->e_magic != 0x5a4d) || (nth->Signature != 0x4550) )
                {
                        break;
                }

                pOEP = (PVOID)( poh->AddressOfEntryPoint + (char *)pImageBase );
                BaseAddress = pOEP;


                if((ULONG64)pOEP<(ULONG64)0x7FFFFFFF)
                {
                        RegionSize=sizeof(fuck32);
                }
                else
                {
                        RegionSize=sizeof(fuck64);
                }       

                status = NtProtectVirtualMemory((HANDLE)-1,&BaseAddress,&RegionSize,PAGE_EXECUTE_READWRITE,&OldProtect);

                if(NT_SUCCESS(status))
                {
                        __try
                        {
                                if((ULONG64)pOEP<(ULONG64)0x7FFFFFFF)
                                {                               
                                        RtlCopyMemory(pOEP,fuck32,sizeof(fuck32));
                                        //SafeMemCopy(pOEP,fuck32,sizeof(fuck32));
                                }
                                else
                                {
                                        RtlCopyMemory(pOEP,fuck64,sizeof(fuck64));
                                        //SafeMemCopy(pOEP,fuck64,sizeof(fuck64));
                                }
                        }
                        __except(1)
                        {
                                ;
                        }
                }

                ObDereferenceObject(pEprocess);
                KeUnstackDetachProcess(&ks);
               


        } while (FALSE);

        PsTerminateSystemThread(STATUS_SUCCESS);
}我修改了一下你的代码,在执行到 NtProtectVirtualMemory 的时候卡住了,求教。

Tesla.Angela 发表于 2013-6-9 18:07:54

“卡住了”是什么意思?
找不到NtProtectVirtualMemory的地址?
NtProtectVirtualMemory的地址有错?
NtProtectVirtualMemory返回失败?
执行NtProtectVirtualMemory的线程死锁了?
执行到NtProtectVirtualMemory蓝屏了?

xiaoc1026 发表于 2013-6-9 18:16:27

Tesla.Angela 发表于 2013-6-9 18:07 static/image/common/back.gif
“卡住了”是什么意思?
找不到NtProtectVirtualMemory的地址?
NtProtectVirtualMemory的地址有错?


NtProtectVirtualMemory地址获取到了,
NtProtectVirtualMemory 也执行了
NtProtectVirtualMemory 退不出来了,我不知道是不是它里面死锁了。

系统没有蓝屏

Tesla.Angela 发表于 2013-6-9 18:53:30

xiaoc1026 发表于 2013-6-9 18:16 static/image/common/back.gif
NtProtectVirtualMemory地址获取到了,
NtProtectVirtualMemory 也执行了
NtProtectVirtualMemory 退不出 ...

你确定地址没有找错?
如果没有错,但是卡住的话,那我就不知道什么原因了。

最后多嘴一句,写代码要理解代码的意思,感觉你的相关知识欠缺很多,啥相关知识都不知道,就想搞出相应的功能是不可能的。
另外,你检查一下你获取SSDT函数地址的代码是否可靠,我曾经在论坛上发过一份可靠的代码。

xiaoc1026 发表于 2013-6-11 13:42:34

Tesla.Angela 发表于 2013-6-9 18:53 static/image/common/back.gif
你确定地址没有找错?
如果没有错,但是卡住的话,那我就不知道什么原因了。



恶补了一下,NtProtectVirtualMemory调用失败是因为传入地址是内核地址,还需要另外申请R3内存做转换,传入。
后来我又用之前MDL 的方法修改,之前MDL无效是因为 MmProbeAndLockPages 的第三个参数传入的可写属性,这里应该先传入IoReadAccess只读属性,再在 MmProtectMdlSystemAddress 修改为可写。

最后修改成功了,但是不是我要的效果……,DLL是被拦截的,同时进程也起不来了。。。
我的目的只是想让DLL加载失败,进程还是可以起来的,我方法用错了吗?有别的方法实现我这个功能吗?

Tesla.Angela 发表于 2013-6-11 20:29:08

xiaoc1026 发表于 2013-6-11 13:42 static/image/common/back.gif
恶补了一下,NtProtectVirtualMemory调用失败是因为传入地址是内核地址,还需要另外申请R3内存做转换,传 ...

你拦截的是不是程序必须用到的DLL???
如果是的话进程能跑起来才怪。
比如一个VB程序,你如果拦截了msvbvm60.dll,你认为此程序还能跑起来么?

jsfw 发表于 2015-12-15 11:57:57

Tesla.Angela说DenyLoadDll需要在SystemThread中执行, 但是等到SystemThread执行时,dll已经被加载了, 再改dll入口点已经没有意义了, 如果在LoadImageNotifyRoutine回调函数中用KeWaitForSingleObject等待SystemThread修改入口点成功, 不知道为什么线程会死锁, Tesla.Angela能不能给解释一下, 这种情况怎么处理?
页: [1]
查看完整版本: 求助拦截DLL加载问题