Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Tracing NT Kernel-Mode Calls


April 2000/Tracing NT Kernel-Mode Calls/Figure 2

Figure 2: Reading import descriptors

Excerpt from Intrcpt.cpp

/*-----------------------------------------------------------------

   FUNCTION: Interceptor::iInterceptImportedFunctionsInModule

   PURPOSE:  Intercept functions imported by the specified
    module as we were instructed by the config file
      
   PARAMETERS:                   .
                                  
    PVOID p_pModuleBaseAddress  Base address of the module
    PCSTR p_pszFileName         Name of the file for this module  
    bool  p_bRestore            Undo the interception
    bool  p_bUseFile - If true -read the import info from the file.
                        NT drivers may have import descriptors in
                        "INIT" section, which is discardable.
                        Therefore, we will try to read it from file

   RETURN VALUE:
      int       Number of intercepted functions
                0 if no functions of interest were found
                -1 on error
-----------------------------------------------------------------*/
int Interceptor::iInterceptImportedFunctionsInModule
(
    PVOID p_pModuleBaseAddress,
    PCSTR p_pszFileName,
    bool  p_bRestore,
    bool  p_bUseFile
)
{
    if(!p_pModuleBaseAddress || 
        ULONG(p_pModuleBaseAddress) < 0x80000000)
        return 0; // we don't work with user addresses
    PIMAGE_NT_HEADERS l_pNTHeader = (PIMAGE_NT_HEADERS)
        pCheckModuleHeader(p_pModuleBaseAddress);
    if(!l_pNTHeader)
    {
        MYTRACE(TF_Error, 
            "ERROR : cannot recognize module header %s at %x",
            p_pszFileName, p_pModuleBaseAddress);
        return -1;
    }

    IMAGE_IMPORT_DESCRIPTOR* l_pImportDesc; 

    ULONG l_dwImportsStartRVA = 
        l_pNTHeader->OptionalHeader.DataDirectory
        [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
    if ( !l_dwImportsStartRVA )
    {
        MYTRACE(TF_Error, 
            "ERROR : cannot find import table in module %x",
            p_pModuleBaseAddress);
        return -1;
    }

    l_pImportDesc = (IMAGE_IMPORT_DESCRIPTOR*)
        (ULONG(p_pModuleBaseAddress) + ULONG(l_dwImportsStartRVA));

    // Find the section (usually .idata) that contains the imports.
    PIMAGE_SECTION_HEADER l_pSection = 
       GetEnclosingSectionHeader(l_dwImportsStartRVA, l_pNTHeader);
    if ( !l_pSection )
    {
        MYTRACE(TF_Error, 
            "ERROR : cannot find a section containing the "
            "import table in module %x",
            p_pModuleBaseAddress);
        return -1;
    }

    ULONG l_dwImportFileOffset = 0;
    NTSTATUS l_Status;
    MyFileLocal l_File;
    if(p_bUseFile)
    {
        long l_lDelta = (long)(l_pSection->VirtualAddress - 
                              l_pSection->PointerToRawData);
        //This delta is the difference between the location of this
        //section in memory and in the file. In order to find the 
        //offset in the file of some object, which belongs to this 
        //section, we should subtract the delta from this 
        //object's RVA.

        l_dwImportFileOffset = l_dwImportsStartRVA - l_lDelta;

        //Some file names returned by ZwQuerySystemInformation
        //does not have any directory information. They seems to
        //always be in Winnt\system\drivers. Other have
        //the directory in the form "Winnt\System\". In both cases
        //we should make correction in the directory name to
        //be able to open the file.
        char l_szFilePath[2*_MAX_PATH];
        if(!strchr(p_pszFileName, '\\'))
        {
            //this file name has no directory. 
            //May be it is in Windows\System32\Drivers
            //Try to contruct a full path
            _snprintf(l_szFilePath, sizeof(l_szFilePath),
                "\\SystemRoot\\System32\\Drivers\\%s",
                p_pszFileName);
            p_pszFileName = l_szFilePath;
        }//if(!strchr(p_pszFileName, '\\'))
        else if(!_strnicmp(p_pszFileName, 
            g_Data.m_pParams->m_szWindowsDir+2,
            g_Data.m_pParams->m_iLengthWindowsDir-2))
        {
            //In this case the module name is in form 
            //"\WinNT\some_dir\module_name"
            //Try to contruct a full path
            _snprintf(l_szFilePath, sizeof(l_szFilePath),
                "\\SystemRoot\\%s",
                p_pszFileName + 
                g_Data.m_pParams->m_iLengthWindowsDir-1);

            p_pszFileName = l_szFilePath;
        }
                        
        l_Status = l_File.OpenFile(p_pszFileName,
            false,false, NULL);

        if(!NT_SUCCESS(l_Status))
        {
            return -1;
        }
    }//if(p_bUseFile)

    int l_iNumFunctions = 0;
    while ( 1 )
    {
        IMAGE_IMPORT_DESCRIPTOR l_ImportDescr;
        if(p_bUseFile)
        {
            //Read the next IMAGE_IMPORT_DESCRIPTOR structure
            //from the file
            LARGE_INTEGER l_liOffset;
            l_liOffset.QuadPart = l_dwImportFileOffset;

            l_Status = l_File.ReadWriteFile(false, 
                &l_ImportDescr, sizeof(l_ImportDescr),
                &l_liOffset, NULL);
            if(!NT_SUCCESS(l_Status))
            {
                break;
            }
            l_pImportDesc = &l_ImportDescr;
        }
        //If p_bUseFile == false, we already have l_pImportDesc
        //pointing to the location in memory, where the import
        //descriptor is, unless it is discarded.

        // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
        if ( (l_pImportDesc->TimeDateStamp==0 ) && 
             (l_pImportDesc->Name==0) )
        {
            break;
        }
        for (IMAGE_THUNK_DATA * l_pThunk = (IMAGE_THUNK_DATA*)
                (ULONG(p_pModuleBaseAddress) + 
                 ULONG(l_pImportDesc->FirstThunk));
            l_pThunk->u1.Function; l_pThunk++)
        {
            if(p_bRestore)
            {
                ASM_APIFunctionStub * l_pStub = 
                    IsItInterceptedFunction(l_pThunk->u1.Function);
                if(l_pStub)
                {
                    InterlockedExchange
                        ((long*)&l_pThunk->u1.Function, 
                        l_pStub->dwGetOriginalFunctionAddress());

                    MYTRACE(TF_Intercepted, 
                        "Import %s restored in %s",
                        l_pStub->m_dwFunctionNameOffset,
                        p_pszFileName);

                    l_iNumFunctions++;
                }
            }
            else
            {
                ASM_APIFunctionStub * l_pStub = 
                    g_Data.m_pConfigMgr->pFindStubByOrigAddress
                        ((void*)l_pThunk->u1.Function);

                if (l_pStub)
                {
                    ULONG l_dwHookAddress = 
                        (ULONG)&l_pStub->m_Code;

                    InterlockedExchange
                        ((long*)&l_pThunk->u1.Function, 
                        l_dwHookAddress);

                    MYTRACE(TF_Intercepted, 
                        "Import %s intercepted in %s",
                        l_pStub->m_dwFunctionNameOffset,
                        p_pszFileName);

                    l_iNumFunctions++;

                }//if(l_dwHookAddress)
            }
        }//for (l_pThunk...

        if(p_bUseFile)
            l_dwImportFileOffset += sizeof(l_ImportDescr);
        else
            l_pImportDesc++;
    }//while (1)
    l_File.CloseFile();
    return l_iNumFunctions;
}//int Interceptor::iInterceptImportedFunctionsInModule

Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.