+- +-

+-User

Welcome, Guest.
Please login or register.
 
 
 
Forgot your password?

+-Stats

Members
Total Members: 131
Latest: meriehileard
New This Month: 1
New This Week: 0
New Today: 0
Stats
Total Posts: 320
Total Topics: 161
Most Online Today: 6
Most Online Ever: 159
(June 29, 2021, 10:20:55 pm)
Users Online
Members: 0
Guests: 6
Total: 6

Author Topic: Get exported function from a remote process.  (Read 473 times)

XutaxKamay

  • Newbie
  • *
  • Posts: 12
    • View Profile
Get exported function from a remote process.
« on: April 11, 2018, 08:04:04 pm »
Hello, I've been doing a simple manual mapper, for the moment I support only relocations, imports and tls callbacks.
I just wanted to know if I did an error somewhere, since I saw a lot of things with exported ordinals functions on internet I'm getting confused at the part of finding by ordinal the right function. (We suppose that I support apisets aswell)
So I've done it this way.
If you need more code, I can send it.

Code: [Select]
uHEX N_Process::Process::GetFunctionReadPE( const PCHAR pcFunctionName , const stdString & sModuleName )
{
    HEX HexOffset = 0;

    bool bIsForwarded = false;

    // The module should be loaded in every cases into the other process, so we find the address of it.
    Pointer pRemotedModuleAddress = FindModule( sModuleName.c_str() );

    if ( pRemotedModuleAddress == nullptr )
    {
        ForceLoadLibrary( sModuleName );
        RefreshGetModules();
    }

    pRemotedModuleAddress = FindModule( sModuleName.c_str() );

    // Gotcha.
    if ( pRemotedModuleAddress != nullptr )
    {
        // Now we have the module address of the remoted process, we can get its full path in the disk.
        stdString sPathToDLL = FindModulePath( pRemotedModuleAddress );

        // Module in disk got deleted instantly just before LoadLibrary was called? No it should really never happen. But who knows.
        if ( sPathToDLL.empty() )
        {
            CONSOLEDEBUG( TEXT( "[%s->GetFunction] couldn't resolve path for module %s\n" ) , sName.c_str() , sModuleName.c_str() );
            return 0;
        }

        HEX hSize = -1;
        auto pDosHeader = ( PIMAGE_DOS_HEADER ) N_FileSystem::ReadFile( sPathToDLL , &hSize );

        if ( hSize <= 0 )
        {
            CONSOLEDEBUG( TEXT( "[%s->GetFunction] couldn't read from path for module %s\n" ) , sName.c_str() , sModuleName.c_str() );
            return 0;
        }

        auto pParentNtHeaders = GetParentNtHeaders( pDosHeader );

        if ( bIsWow64 )
        {
            auto pNtHeaders = ( pNTHeaders32 ) pParentNtHeaders;

            uHEX32 EntryRVA = pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress;
            uHEX32 EntrySize = pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size;

            auto pExportDirectory = ( PIMAGE_EXPORT_DIRECTORY ) ( ( HEX ) pDosHeader
                                                                  + ( HEX ) RvaToRaw32( pNtHeaders
                                                                  , EntryRVA ) );

            if ( pExportDirectory != nullptr )
            {
                puHEX32 pFunctions = ( puHEX32 ) ( ( HEX ) pDosHeader
                                                   + ( HEX ) RvaToRaw32( pNtHeaders
                                                   , pExportDirectory->AddressOfFunctions ) );

                puHEX32 pNames = ( puHEX32 ) ( ( HEX ) pDosHeader
                                               + ( HEX ) RvaToRaw32( pNtHeaders
                                               , pExportDirectory->AddressOfNames ) );

                PWORD pOrdinals = ( PWORD ) ( ( HEX ) pDosHeader
                                              + ( HEX ) RvaToRaw32( pNtHeaders
                                              , pExportDirectory->AddressOfNameOrdinals ) );

                std::string str = pcFunctionName;

                if ( std::all_of( str.begin() , str.end() , ::isdigit ) )
                {
                    uHEX32 hWishOrdinal = ( uHEX32 ) atoi( pcFunctionName );

                    uHEX32 hRVAFunction = pFunctions[ hWishOrdinal - pExportDirectory->Base ];

                    // Forwarded.
                    if ( hRVAFunction > EntryRVA && hRVAFunction < EntryRVA + EntrySize )
                    {
                        std::string sfFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw32( pNtHeaders , hRVAFunction ) );

                        size_t sdotPos = sfFuncName.find( "." );

                        if ( sdotPos != std::string::npos )
                        {
                            stdString sModule( AutoConvertS( sfFuncName.substr( 0 , sdotPos + 1 ) ) );

                            sModule.resize( sModule.size() + 3 );
                            sModule[ sdotPos + 1 ] = TEXT( 'D' );
                            sModule[ sdotPos + 2 ] = TEXT( 'L' );
                            sModule[ sdotPos + 3 ] = TEXT( 'L' );

                            std::string sRealFuncName = sfFuncName.substr( sdotPos + 1 , sfFuncName.size() );

                            HexOffset = GetFunctionReadPE( ( PCHAR ) sRealFuncName.c_str() , sModule.c_str() );

                            bIsForwarded = true;
                        }
                    }
                    else
                    {
                        Pointer pFunctionAddress = ( Pointer ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw32( pNtHeaders , hRVAFunction ) );

                        HexOffset = ( HEX ) RawToRva32( pNtHeaders , ( uHEX32 ) ( ( HEX ) pFunctionAddress - ( HEX ) pDosHeader ) );
                    }

                    goto FoundExport;
                }
                else
                {
                    for ( uHEX32 i = 0; i != pExportDirectory->NumberOfNames; i++ )
                    {
                        const PCHAR sFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw32( pNtHeaders , pNames[ i ] ) );

                        if ( !_stricmp( sFuncName , str.c_str() ) )
                        {
                            uHEX32 hReadOrdinal = ( uHEX32 ) pOrdinals[ i ];

                            uHEX32 hRVAFunction = pFunctions[ hReadOrdinal ];

                            // Forwarded.
                            if ( hRVAFunction > EntryRVA && hRVAFunction < EntryRVA + EntrySize )
                            {
                                std::string sfFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw32( pNtHeaders , hRVAFunction ) );

                                size_t sdotPos = sfFuncName.find( "." );

                                if ( sdotPos != std::string::npos )
                                {
                                    stdString sModule( AutoConvertS( sfFuncName.substr( 0 , sdotPos + 1 ) ) );

                                    sModule.resize( sModule.size() + 3 );
                                    sModule[ sdotPos + 1 ] = TEXT( 'D' );
                                    sModule[ sdotPos + 2 ] = TEXT( 'L' );
                                    sModule[ sdotPos + 3 ] = TEXT( 'L' );

                                    std::string sRealFuncName = sfFuncName.substr( sdotPos + 1 , sfFuncName.size() );

                                    HexOffset = GetFunctionReadPE( ( PCHAR ) sRealFuncName.c_str() , sModule.c_str() );

                                    bIsForwarded = true;
                                }
                            }
                            else
                            {
                                Pointer pFunctionAddress = ( Pointer ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw32( pNtHeaders , hRVAFunction ) );

                                HexOffset = ( HEX ) RawToRva32( pNtHeaders , ( uHEX32 ) ( ( HEX ) pFunctionAddress - ( HEX ) pDosHeader ) );
                            }

                            goto FoundExport;
                        }
                    }

                    CONSOLEDEBUG( TEXT( "GetFunctionReadPE: Couldn't find %s for module %s\n" ) , AutoConvertS( pcFunctionName ) , sModuleName.c_str() );

                    return 0;
                }
            }
        }
        else
        {
            auto pNtHeaders = ( pNTHeaders64 ) pParentNtHeaders;

            uHEX32 EntryRVA = pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].VirtualAddress;
            uHEX32 EntrySize = pNtHeaders->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ].Size;

            auto pExportDirectory = ( PIMAGE_EXPORT_DIRECTORY ) ( ( HEX ) pDosHeader
                                                                  + ( HEX ) RvaToRaw64( pNtHeaders
                                                                  , EntryRVA ) );

            if ( pExportDirectory != nullptr )
            {
                puHEX32 pFunctions = ( puHEX32 ) ( ( HEX ) pDosHeader
                                                   + ( HEX ) RvaToRaw64( pNtHeaders
                                                   , pExportDirectory->AddressOfFunctions ) );

                puHEX32 pNames = ( puHEX32 ) ( ( HEX ) pDosHeader
                                               + ( HEX ) RvaToRaw64( pNtHeaders
                                               , pExportDirectory->AddressOfNames ) );

                PWORD pOrdinals = ( PWORD ) ( ( HEX ) pDosHeader
                                              + ( HEX ) RvaToRaw64( pNtHeaders
                                              , pExportDirectory->AddressOfNameOrdinals ) );

                std::string str = pcFunctionName;

                if ( std::all_of( str.begin() , str.end() , ::isdigit ) )
                {
                    uHEX32 hWishOrdinal = ( uHEX32 ) atoi( pcFunctionName );

                    uHEX32 hRVAFunction = pFunctions[ hWishOrdinal - pExportDirectory->Base ];

                    // Forwarded.
                    if ( hRVAFunction > EntryRVA && hRVAFunction < EntryRVA + EntrySize )
                    {
                        std::string sfFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw64( pNtHeaders , hRVAFunction ) );

                        size_t sdotPos = sfFuncName.find( "." );

                        if ( sdotPos != std::string::npos )
                        {
                            stdString sModule( AutoConvertS( sfFuncName.substr( 0 , sdotPos + 1 ) ) );

                            sModule.resize( sModule.size() + 3 );
                            sModule[ sdotPos + 1 ] = TEXT( 'D' );
                            sModule[ sdotPos + 2 ] = TEXT( 'L' );
                            sModule[ sdotPos + 3 ] = TEXT( 'L' );

                            std::string sRealFuncName = sfFuncName.substr( sdotPos + 1 , sfFuncName.size() );

                            HexOffset = GetFunctionReadPE( ( PCHAR ) sRealFuncName.c_str() , sModule.c_str() );

                            bIsForwarded = true;
                        }
                    }
                    else
                    {
                        Pointer pFunctionAddress = ( Pointer ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw64( pNtHeaders , hRVAFunction ) );

                        HexOffset = ( HEX ) RawToRva64( pNtHeaders , ( uHEX32 ) ( ( HEX ) pFunctionAddress - ( HEX ) pDosHeader ) );
                    }

                    goto FoundExport;
                }
                else
                {
                    for ( uHEX32 i = 0; i != pExportDirectory->NumberOfNames; i++ )
                    {
                        const PCHAR sFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw64( pNtHeaders , pNames[ i ] ) );

                        if ( !_stricmp( sFuncName , str.c_str() ) )
                        {
                            uHEX32 hReadOrdinal = ( uHEX32 ) pOrdinals[ i ];

                            uHEX32 hRVAFunction = pFunctions[ hReadOrdinal ];

                            // Forwarded.
                            if ( hRVAFunction > EntryRVA && hRVAFunction < EntryRVA + EntrySize )
                            {
                                std::string sfFuncName = ( PCHAR ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw64( pNtHeaders , hRVAFunction ) );

                                size_t sdotPos = sfFuncName.find( "." );

                                if ( sdotPos != std::string::npos )
                                {
                                    stdString sModule( AutoConvertS( sfFuncName.substr( 0 , sdotPos + 1 ) ) );

                                    sModule.resize( sModule.size() + 3 );
                                    sModule[ sdotPos + 1 ] = TEXT( 'D' );
                                    sModule[ sdotPos + 2 ] = TEXT( 'L' );
                                    sModule[ sdotPos + 3 ] = TEXT( 'L' );

                                    std::string sRealFuncName = sfFuncName.substr( sdotPos + 1 , sfFuncName.size() );

                                    HexOffset = GetFunctionReadPE( ( PCHAR ) sRealFuncName.c_str() , sModule.c_str() );

                                    bIsForwarded = true;
                                }
                            }
                            else
                            {
                                Pointer pFunctionAddress = ( Pointer ) ( ( HEX ) pDosHeader + ( HEX ) RvaToRaw64( pNtHeaders , hRVAFunction ) );

                                HexOffset = ( HEX ) RawToRva64( pNtHeaders , ( uHEX32 ) ( ( HEX ) pFunctionAddress - ( HEX ) pDosHeader ) );
                            }

                            goto FoundExport;
                        }
                    }

                    CONSOLEDEBUG( TEXT( "GetFunctionReadPE: Couldn't find %s for module %s\n" ) , AutoConvertS( pcFunctionName ) , sModuleName.c_str() );

                    return 0;
                }
            }
        }

FoundExport:

        uHEX hFinal;

        if ( !bIsForwarded )
            hFinal = ( ( uHEX ) pRemotedModuleAddress + HexOffset );
        else
            hFinal = ( uHEX ) HexOffset;

        CONSOLEColorDEBUG( FOREGROUND_GREEN , TEXT( "Resolved: %s for module %s (0x%p)\n" ) , AutoConvertS( pcFunctionName ) , sModuleName.c_str() , hFinal );

        FreeAlloc( pDosHeader );

        return hFinal;
    }
    else
    {
        CONSOLEDEBUG( TEXT( "[%s->GetFunction] couldn't find module %s from process\n" ) , sName.c_str() , sModuleName.c_str() );
        return 0;
    }
}


PS: I'm getting stuck at exception handling since there is not a lot of docs I saw about it (I've googled but I couldn't find something clear) , so if anyone know how it works, or know a simple document that would explain it, it would save me time, thank you.

Share on Facebook Share on Twitter

Useful Useful x 1 View List

zwclose7

  • Administrator
  • Full Member
  • *****
  • Posts: 155
  • I love anime and science!
    • View Profile
    • My blog
Re: Get exported function from a remote process.
« Reply #1 on: April 12, 2018, 12:55:25 pm »
If you want to perform manual DLL injection, you can see this example.
http://zwclose7.createaforum.com/windows-application/manual-dll-injection/
Like Like x 1 View List

XutaxKamay

  • Newbie
  • *
  • Posts: 12
    • View Profile
Re: Get exported function from a remote process.
« Reply #2 on: April 12, 2018, 07:43:08 pm »
Hello, thank you for your anwser.
In fact I just wanted to know if the I'm doing the right way for finding an ordinal function in the export directory ? ( AddressOfFunctions[Ordinal - Base] ?)

I looked at your code already, but it would still crash my dll (https://www.dropbox.com/s/56c61vpx899ufpo/DLL_Test.dll?dl=0) because it doesn't support TLS (I support only tls callback, but no static tls etc) and exceptions.
Your code also needs to have the headers written in memory, and because of that, the DLL can be reconstructed more easily. (I'm doing in a way where it doesn't need the headers written in the virtual memory of the targeted process, or even in the client)
What I'm doing is basically resolving everything in a server where it streams the sections to the client and copy them to the process, and call entrypoint.
I just wanted to know also if someone have some documents about exception handling (IMAGE_DIRECTORY_ENTRY_EXCEPTION), or know how it should be handled.

Thank you for your reply in advance!
« Last Edit: April 12, 2018, 08:27:29 pm by XutaxKamay »

 

+-Recent Topics

Power Blast Keto Reviews by meriehileard
September 12, 2021, 07:38:32 pm

Independent Call Girls in Chandigarh by dilpreetkaur
June 21, 2021, 01:02:52 pm

Hi zwclose7. How to create process by using NT apis? by zwclose7
June 01, 2021, 03:09:52 pm

Poison of the Day by zwclose7
March 16, 2020, 06:45:08 pm

IRC by AzeS
February 17, 2020, 08:18:01 am

Native API tutorial by hMihaiDavid
January 08, 2019, 02:11:02 am

The properties of GP nerve agent by xchg
October 19, 2018, 07:40:57 pm

A new route of synthesis for G-series agents by Basquyatti
October 15, 2018, 06:12:57 am

Synthesis of Methylisobutylcarbinylsarin (GH) by APC process by Basquyatti
October 14, 2018, 07:55:33 am

Synthesis conventional of Sarin by Basquyatti
October 02, 2018, 07:57:32 am