LoadLibrary分析

LoadLibrary下面分别调用了LoadLibraryEx。LoadLibraryEx里面有几个参数哦。。可以把文件调入进来不执行DllMain,或者当做资源文件加载进来。然后通过RtlAnsiStringToUnicodeString将文件名转换为UNICODE String,然后调用下层函数 LoadLibraryExW..(这里学到2个函数wcschr,wcsrchr,wcslen看来ntdll里面也有很多字符串函数)。然后就是根据环境变量看看系统目录(如果当前目录下没有dll,那就到系统目录下windows/system32下去找dll)。
然后在zwOpenFile下断吧。(这里是打开dll文件。) zwopenfile后调用ZwCreateSection函数。顾名思意大概也猜到什么意思了。然后就是调用 ZwMapViewOfSection函数。呵呵。开始装载执行体进内存了。
然后又看到一个不错的函数-RtlImageNtHeader---用起来真方便啊。(LdrEnumerateLoadedModules这个函数也不错哦。在ntdll中),随后用RtlImageDirectoryEntryToData,该函数我查到资料如下:
DWORD RtlImageDirectoryEntryToData(DWORD imagebase,BOOL bVA,DWORD dwDataDirectoryIndex, DWORD *size);
其中,imagebase 为模块基址,也就是MZ开头的地方, bVA为真表示函数返回一个VA, 否则函数返回一个PointerToRawData(减去基址就是在文件中的位置),
dwDataDirectoryIndex为索引值, 从0到f,如0表示导出表。
size为接受这项数据目录大小的指针。
如果该索引不存在, 那么函数返回0, 并且不改变size指针的值。
解释的很清楚了。。呵呵。。(第一次看到这个函数,系统调用查询时COM的DataDirectory。)
随后通过在系统中加载的基地址和dll的入口点,代码如下:
7C93C6D9    8BFF            mov     edi, edi
7C93C6DB    55              push    ebp
7C93C6DC    8BEC            mov     ebp, esp
7C93C6DE    FF75 08         push    dword ptr [ebp+8]
7C93C6E1    E8 533CFFFF     call    RtlImageNtHeader
7C93C6E6    85C0            test    eax, eax
7C93C6E8    74 0A           je      short 7C93C6F4
7C93C6EA    8B40 28         mov     eax, dword ptr [eax+28]                        ; dll的入口点
7C93C6ED    85C0            test    eax, eax
7C93C6EF    74 03           je      short 7C93C6F4
7C93C6F1    0345 08         add     eax, dword ptr [ebp+8]                         ; [ebp+8]为加载的基地址
7C93C6F4    5D              pop     ebp
7C93C6F5    C2 0400         retn    4
 
随后来到重定位表项:
7C93DF15    33DB            xor     ebx, ebx
7C93DF17    385D C2         cmp     byte ptr [ebp-3E], bl
7C93DF1A    0F84 89050000   je      7C93E4A9
7C93DF20    F646 34 04      test    byte ptr [esi+34], 4
7C93DF24    0F84 12E90000   je      7C94C83C
7C93DF2A    8B45 A0         mov     eax, dword ptr [ebp-60]
7C93DF2D    F640 16 01      test    byte ptr [eax+16], 1
7C93DF31    75 1B           jnz     short 7C93DF4E
7C93DF33    895D 84         mov     dword ptr [ebp-7C], ebx
7C93DF36    8D45 84         lea     eax, dword ptr [ebp-7C]
7C93DF39    50              push    eax
7C93DF3A    6A 05           push    5                                                ; 到了重定位表项了
7C93DF3C    6A 01           push    1
7C93DF3E    FF75 E4         push    dword ptr [ebp-1C]
7C93DF41    E8 0024FFFF     call    RtlImageDirectoryEntryToData
7C93DF46    3BC3            cmp     eax, ebx
7C93DF48    0F84 E5E80000   je      7C94C833
7C93DF4E    C645 C3 01      mov     byte ptr [ebp-3D], 1
7C93DF52    B8 5CF8997C     mov     eax, 7C99F85C
7C93DF57    8945 80         mov     dword ptr [ebp-80], eax
 
然后通过函数
ZwProtectVirtualMemory(
  IN HANDLE              ProcessHandle,
  IN OUT PVOID            *BaseAddress,
  IN OUT PULONG          NumberOfBytesToProtect,
  IN ULONG                NewAccessProtection,
  OUT PULONG              OldAccessProtection );设置各个段的属性。分别可以是读写执行等。
-----------------------------------------------------------------
精彩地方来了,重定位的地方来了。。呵呵。。
7C93E06D    8BFF            mov     edi, edi
7C93E06F    55              push    ebp
7C93E070    8BEC            mov     ebp, esp
7C93E072    83EC 10         sub     esp, 10
7C93E075    53              push    ebx
7C93E076    56              push    esi
7C93E077    57              push    edi
7C93E078    FF75 08         push    dword ptr [ebp+8]
7C93E07B    33DB            xor     ebx, ebx
7C93E07D    895D FC         mov     dword ptr [ebp-4], ebx
7C93E080    E8 B422FFFF     call    RtlImageNtHeader
7C93E085    8BF0            mov     esi, eax
7C93E087    3BF3            cmp     esi, ebx
7C93E089    0F84 17B10200   je      7C9691A6
7C93E08F    8B7E 34         mov     edi, dword ptr [esi+34]          ; [IMAGE_OPTIONAL_HEADER].ImageBase
7C93E092    8D45 FC         lea     eax, dword ptr [ebp-4]
7C93E095    50              push    eax
7C93E096    6A 05           push    5
7C93E098    6A 01           push    1
7C93E09A    FF75 08         push    dword ptr [ebp+8]                ; MZ基地址
7C93E09D    897D F8         mov     dword ptr [ebp-8], edi
7C93E0A0    E8 A122FFFF     call    RtlImageDirectoryEntryToData     ; 获得重定位数据
7C93E0A5    8BC8            mov     ecx, eax
7C93E0A7    85C9            test    ecx, ecx
7C93E0A9    74 54           je      short 7C93E0FF
7C93E0AB    395D FC         cmp     dword ptr [ebp-4], ebx
7C93E0AE    74 4F           je      short 7C93E0FF
7C93E0B0    8B45 08         mov     eax, dword ptr [ebp+8]           ; MZ基地址
7C93E0B3    2BC7            sub     eax, edi                         ; 执行体映像地址-建议加载地址
7C93E0B5    99              cdq
7C93E0B6    0345 0C         add     eax, dword ptr [ebp+C]
7C93E0B9    8BFA            mov     edi, edx
7C93E0BB    137D 10         adc     edi, dword ptr [ebp+10]
7C93E0BE    8945 F0         mov     dword ptr [ebp-10], eax          ; delta = [ebp-010] = 执行体映像地址-建议加载地址
7C93E0C1    897D F4         mov     dword ptr [ebp-C], edi
7C93E0C4    8B41 04         mov     eax, dword ptr [ecx+4]           ; ecx=重定位段地址
7C93E0C7    2945 FC         sub     dword ptr [ebp-4], eax           ; 重定位段的大小
7C93E0CA    57              push    edi
7C93E0CB    FF75 F0         push    dword ptr [ebp-10]
7C93E0CE    8D59 08         lea     ebx, dword ptr [ecx+8]           ; 重定位指针
7C93E0D1    8B09            mov     ecx, dword ptr [ecx]             ; RVA基地址
7C93E0D3    034D 08         add     ecx, dword ptr [ebp+8]           ; RAV+段基地址得到虚拟地址
7C93E0D6    8D70 F8         lea     esi, dword ptr [eax-8]           ; 重定位段大小-头大小8
7C93E0D9    53              push    ebx                              ; 重定位项
7C93E0DA    D1EE            shr     esi, 1                           ; 除2,得到需要重定位项目的个数
7C93E0DC    56              push    esi
7C93E0DD    51              push    ecx                              ; 基地址指针
7C93E0DE    E8 33000000     call    7C93E116                         ; 这里就是重定位吧
7C93E0E3    8BC8            mov     ecx, eax
7C93E0E5    85C9            test    ecx, ecx
7C93E0E7    0F84 BCB00200   je      7C9691A9
7C93E0ED    837D FC 00      cmp     dword ptr [ebp-4], 0
 
 
然后进入 Call 7c93e116..
具体重定位算法,呵呵。先看看下面重定位的组织方式吧:
void GetRelocInfo()
{
    DWORD dwOffset=0;
    UINT nIndex=1;
    if( m_bIsValidPE && m_pOptionHeader ) {
        //DataDirectory的第五项是重定位表
        if ( m_pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0 &&
            m_pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0 ) {//重定位表为空
            return;
        }
        dwOffset = GetFileOffset(  m_pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress );
        PIMAGE_BASE_RELOCATION pReloc = (PIMAGE_BASE_RELOCATION)(m_pFileBuf + dwOffset );
        while ( pReloc->VirtualAddress ) {
            RelocItem RI;
            UINT i=0;
            DWORD *pItem = (DWORD *)pReloc + 2;
            WORD wOffset = 0;
            ZeroMemory(&RI, sizeof(RelocItem) );
            RI.nIndex = nIndex;
            strcpy(RI.strSectionName , GetSectionName( pReloc->VirtualAddress ));//取所在区的名称
            RI.nNum = (pReloc->SizeOfBlock-( sizeof(DWORD) << 1 ) ) /sizeof(WORD);//得到TypeOffset数量
            while ( i < RI.nNum  ) {
                RelocChunk RC;
                wOffset = (WORD) (*pItem);
                switch( ( wOffset & 0xF000 ) >> 12 )
                {//每个重定位项的类型
                case IMAGE_REL_BASED_ABSOLUTE:
                    strcpy(RC.type , "ABSOLUTE(0)");
                    break;
                case IMAGE_REL_BASED_HIGH:
                    strcpy(RC.type , "HIGH(1)");
                    break;
                case IMAGE_REL_BASED_LOW:
                    strcpy(RC.type ,"LOW(2)");
                    break;
                case IMAGE_REL_BASED_HIGHLOW:
                    strcpy(RC.type ,"HIGHLOW(3)");
                    break;
                case IMAGE_REL_BASED_HIGHADJ:
                    strcpy(RC.type ,"HIGHADJ(4)");
                    break;
                case IMAGE_REL_BASED_MIPS_JMPADDR:
                    strcpy(RC.type ,"JMPADDR(5)");
                    break;
                    /*case IMAGE_REL_BASED_MIPS_JMPADDR16:
                    RC.type = _T("JMPADDR16(9)");
                    break;*/
                case IMAGE_REL_BASED_IA64_IMM64:
                    strcpy(RC.type ,"IMM64(9)");
                    break;
                case IMAGE_REL_BASED_DIR64:
                    strcpy(RC.type ,"DIR64(10)");
                    break;
                }               
                if( wOffset != 0 ) {
                    RC.dwRVA = pReloc->VirtualAddress+(wOffset&0x0FFF);
                    RC.dwFarAddr = * ( (DWORD*)( m_pFileBuf + GetFileOffset( RC.dwRVA ) ) );
                }
                else {//结束了的情况
                    RC.dwRVA = 0;
                    RC.dwFarAddr = 0;
                }
                RC.nIndex = ++i;//编号               
//                RI.chunk.push_back( RC );               
                pItem =(DWORD *)( (WORD*) pItem + 1 );//移到下一个Item               
            }
//            m_reloc.push_back( RI );           
            pReloc=(PIMAGE_BASE_RELOCATION)((DWORD)pReloc + pReloc->SizeOfBlock);           
        }       
    }/*( m_bIsValidPE && m_pOptionHeader )*/
}
具体ntdll里面的汇编如下,很简单:
7C93E116    8BFF            mov     edi, edi
7C93E118    55              push    ebp
7C93E119    8BEC            mov     ebp, esp
7C93E11B    51              push    ecx
7C93E11C    51              push    ecx
7C93E11D    837D 0C 00      cmp     dword ptr [ebp+C], 0
7C93E121    53              push    ebx
7C93E122    56              push    esi
7C93E123    57              push    edi
7C93E124    74 39           je      short 7C93E15F
7C93E126    8B55 14         mov     edx, dword ptr [ebp+14]
7C93E129    90              nop
7C93E12A    90              nop
7C93E12B    90              nop
7C93E12C    90              nop
7C93E12D    90              nop
7C93E12E    90              nop
7C93E12F    90              nop
7C93E130    8B75 10         mov     esi, dword ptr [ebp+10]          ; [ebp+010]重定位段指针
7C93E133    0FB706          movzx   eax, word ptr [esi]
7C93E136    FF4D 0C         dec     dword ptr [ebp+C]                ; [ebp+0c]需要重定位的个数
7C93E139    8BC8            mov     ecx, eax
7C93E13B    81E1 FF0F0000   and     ecx, 0FFF
7C93E141    034D 08         add     ecx, dword ptr [ebp+8]           ; 得到了需要重定位的地址咯。,[ebp+8]基地址指针
7C93E144    C1E8 0C         shr     eax, 0C
7C93E147    83F8 0A         cmp     eax, 0A
7C93E14A    77 1D           ja      short 7C93E169
7C93E14C    FF2485 7DE4937C jmp     dword ptr [eax*4+7C93E47D]       ; eax==3,就修正,0就不修正
7C93E153    0111            add     dword ptr [ecx], edx             ; edx是delta..呵呵。。
7C93E155    8345 10 02      add     dword ptr [ebp+10], 2
7C93E159    837D 0C 00      cmp     dword ptr [ebp+C], 0
7C93E15D  ^ 75 D1           jnz     short 7C93E130
7C93E15F    8B45 10         mov     eax, dword ptr [ebp+10]
7C93E162    5F              pop     edi
7C93E163    5E              pop     esi
7C93E164    5B              pop     ebx
7C93E165    C9              leave
7C93E166    C2 1400         retn    14
7C93E169    33C0            xor     eax, eax
7C93E16B  ^ EB F5           jmp     short 7C93E162
--------------------------
分析就到这吧。。先睡哦。
Copy Right by lwglucky . QQ:14465340

你可能感兴趣的:(职场,休闲,逆向分析,loadlibrary,重定位)