Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8531809
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T09:34:16+00:00 2026-06-11T09:34:16+00:00

I have a legacy application, which contains a grid with data I need to

  • 0

I have a legacy application, which contains a grid with data I need to extract.

I don’t have the code for that application and it is impossible to get the data out of it with normal means (like programmatically selecting all cells and copying them into clipboard).

So I decided to use DLL injection as described in section “II. The CreateRemoteThread & LoadLibrary Technique” at

http://www.codeproject.com/Articles/4610/Three-Ways-to-Inject-Your-Code-into-Another-Proces

My plan is

  1. To load a DLL into the address space of the legacy application.
  2. Make the DLL read the data from the grid and write them out (e. g. via a named pipe).

The first step is to inject the DLL into the address space of the legacy application (step a) above).

I’ve written following code for that:

int  InjectDll            (HANDLE hProcess);

int _tmain(int argc, _TCHAR* argv[])
{
    printf("DllInjector\n");

    /**
     * Find out PID of the legacy application (START)
     */
    HWND windowHandle = FindWindowW(NULL, L"FORMSSSSS");
    DWORD* processID = new DWORD;
    GetWindowThreadProcessId(windowHandle, processID);

    DWORD delphiAppProcessId = *processID;
    /**
     * Find out PID of the legacy application (END)
     */

    printf("Process ID of legacy app: %lu\n", delphiAppProcessId);

    // Now we need the handle of the legacy app
    HANDLE hProcess = OpenProcess(
    PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ,
    FALSE, delphiAppProcessId);

    if (hProcess != NULL)
    {
        printf("Found handle, ready for injection\n");
        int result = InjectDll(hProcess);
        CloseHandle( hProcess );
        printf("Injection complete, result=%d\n", result);

    }
    else
    {
        printf("Handle not found\n");
    }

    system("pause");

    return 0;
}

int InjectDll( HANDLE hProcess )
{
    HANDLE hThread;
    const char* const szLibPath = "D:\\mycompany\\SampleDll\\Debug\\SampleDll.dll";
    void*  pLibRemote = 0;  // the address (in the remote process) where
                            // szLibPath will be copied to;
    DWORD  hLibModule = 0;  // base adress of loaded module (==HMODULE);

    HMODULE hKernel32 = ::GetModuleHandle(L"Kernel32");

    // 1. Allocate memory in the remote process for szLibPath
    // 2. Write szLibPath to the allocated memory
    pLibRemote = ::VirtualAllocEx( hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE );
    if( pLibRemote == NULL )
        return false;
    ::WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath,sizeof(szLibPath),NULL);

    // Load "LibSpy.dll" into the remote process 
    // (via CreateRemoteThread & LoadLibrary)
    hThread = ::CreateRemoteThread( hProcess, NULL, 0,  
                    (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"LoadLibraryA"), 
                    pLibRemote, 0, NULL );
    if( hThread == NULL )
        goto JUMP;

    ::WaitForSingleObject( hThread, INFINITE );

    // Get handle of loaded module
    ::GetExitCodeThread( hThread, &hLibModule );
    ::CloseHandle( hThread );

JUMP:   
    ::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );
    if( hLibModule == NULL ) // (1)
        return false;


    // Unload "LibSpy.dll" from the remote process 
    // (via CreateRemoteThread & FreeLibrary)
    hThread = ::CreateRemoteThread( hProcess,
                NULL, 0,
                (LPTHREAD_START_ROUTINE) ::GetProcAddress(hKernel32,"FreeLibrary"),
                (void*)hLibModule,
                 0, NULL );
    if( hThread == NULL )   // failed to unload
        return false;

    ::WaitForSingleObject( hThread, INFINITE );
    ::GetExitCodeThread( hThread, &hLibModule );
    ::CloseHandle( hThread );

    // return value of remote FreeLibrary (=nonzero on success)
    return hLibModule;
}

Some comments:

  1. The legacy program has the title “FORMSSSSS”.
  2. The sample DLL has following DllMain method:

–

BOOL APIENTRY DllMain( HMODULE hModule,
DWORD  ul_reason_for_call,
LPVOID lpReserved

{
    OutputDebugStringA("DllMain called: ");
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        OutputDebugStringA("DLL_PROCESS_ATTACH\n");
    case DLL_THREAD_ATTACH:
        OutputDebugStringA("DLL_THREAD_ATTACH\n");
    case DLL_THREAD_DETACH:
        OutputDebugStringA("DLL_THREAD_DETACH\n");
    case DLL_PROCESS_DETACH:
        OutputDebugStringA("DLL_PROCESS_DETACH\n");
        break;
    }
    return TRUE;
}

When it is called, a text is written into the standard output of the application.


When I run the program above (the one with _tmain method), I expect to see the text

DllMain called: DLL_PROCESS_ATTACH

in the console output (it means that the DLL injection was successful).

But it doesn’t happen.


One potential cause is that the PID of the legacy application is determined incorrectly:

HWND windowHandle = FindWindowW(NULL, L"FORMSSSSS");
DWORD* processID = new DWORD;
GetWindowThreadProcessId(windowHandle, processID);

DWORD delphiAppProcessId = *processID;

But the value delphiAppProcessId is the same as the PID displayed in the task manager, so I can exclude this potential bug.


Using the debugger I found out that the execution stops at the line with comment (1):

JUMP:   
    ::VirtualFreeEx( hProcess, pLibRemote, sizeof(szLibPath), MEM_RELEASE );
    if( hLibModule == NULL ) // (1)
        return false;

What do I need to change in order for the sample DLL to be injected into the address space of the application with title “FORMSSSSS” ?

Update, 16.09.2012:

I replaced all occurrences of

sizeof(szLibPath)

by pathLength, where

const int pathLength = strlen(szLibPath)+1;

Now, in

    ::WaitForSingleObject( hThread, INFINITE );
    ::GetExitCodeThread( hThread, &hLibModule );
    ::CloseHandle( hThread );

    // return value of remote FreeLibrary (=nonzero on success)
    return hLibModule;
}

hLibModule is nonzero, which means that the injection was successful.

But I still can’t see the log output of the sample DLL in the output of the program.

Update, 16.09.2012 (2):

When I

a) add a call to AllocConsole() in DllMain of the sample DLL,
b) rebuild it and
c) execute the injecting program,

then a console window appears, which has the same icon as the Delphi application.

When I remove AllocConsole from the DllMain function, and execute the injecting application, the console window does not appear.

So the injection might actually work.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T09:34:17+00:00Added an answer on June 11, 2026 at 9:34 am

    The biggest problem that I can see is that sizeof(szLibPath) evaluates to the size of a pointer. Use strlen(szLibPath)+1 instead.

    For sure that means that your injection will fail because the path that LoadLibraryA receives will be truncated. There may be other problems, but that’s the place to start.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have an application (Legacy code) that contains interface Icomponent with save() methods and
I have a legacy database which contains simple data structures (no CODE refs thank
I have a legacy VB6 application which contains this code: Begin VB.Label LblStDate Alignment
I have some data (produced by a legacy application) that I know is invalid
Suppose that I have a legacy java application with thousands of lines of code
If I have a Server/Client application that both reference the same DLL which contains
We have a legacy VB6 application from which we have migrated the licencing code
I have a legacy application which is (currently) using Django to effectively display data.
I have a legacy MFC C++ application for Win CE 4.2 (x86 ONLY) which
I have a legacy application that I inherited that passes a lot of XML

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.