delorie.com/archives/browse.cgi   search  
Mail Archives: cygwin/2015/02/21/07:03:35

X-Recipient: archive-cygwin AT delorie DOT com
DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id
:list-unsubscribe:list-subscribe:list-archive:list-post
:list-help:sender:from:to:in-reply-to:subject:date:message-id
:mime-version:content-type:content-transfer-encoding; q=dns; s=
default; b=PMigfarg3vKzn2O/2R7wEuT1+WXpT391JvoItcWv1lazGhMhYgF7Y
WZDysqgapl6UQ2k7FS9lWwatqcG2+8Gf1zURao8YSuaiBDmQ+W+cj8Cv2nvmjFoU
zooY8BqC1dUTFduum7NXJqJdh4j9qSKGL1jp5IuUEvhl7caI1er/Lc=
DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id
:list-unsubscribe:list-subscribe:list-archive:list-post
:list-help:sender:from:to:in-reply-to:subject:date:message-id
:mime-version:content-type:content-transfer-encoding; s=default;
bh=ohXVhYOnPvhl9zg/0eMNNG+3uz8=; b=x2yQbxnuhgLG2i36WbF6oTzLB6mH
GkYzudtF7K6bFqwNS5P8oNqH2CqY4P8k2a5zWtP+PAjhFOutM+snp+fnSq8zDFe8
yLqPZQmRYoc7dC2jMnYV85+boI/fmlIya+YL0yyjs0ctsL56jGpVKpTkl3O7hGHG
ro1JLeN9Y7VXji4=
Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm
List-Id: <cygwin.cygwin.com>
List-Subscribe: <mailto:cygwin-subscribe AT cygwin DOT com>
List-Archive: <http://sourceware.org/ml/cygwin/>
List-Post: <mailto:cygwin AT cygwin DOT com>
List-Help: <mailto:cygwin-help AT cygwin DOT com>, <http://sourceware.org/ml/#faqs>
Sender: cygwin-owner AT cygwin DOT com
Mail-Followup-To: cygwin AT cygwin DOT com
Delivered-To: mailing list cygwin AT cygwin DOT com
Authentication-Results: sourceware.org; auth=none
X-Virus-Found: No
X-Spam-SWARE-Status: No, score=1.7 required=5.0 tests=AWL,BAYES_50,KAM_COUK,RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2
X-HELO: smtp.demon.co.uk
From: "Roger Orr" <rogero AT howzatt DOT demon DOT co DOT uk>
To: "'Dennis Hagarty \(dehagart\)'" <dehagart AT cisco DOT com>, <cygwin AT cygwin DOT com>
In-Reply-To: <3FEEC3A37A0B0A48AA326075128C32EE4EE27AEC@xmb-rcd-x01.cisco.com>
Subject: RE: Very slow Cygwin startup on Windows 7
Date: Sat, 21 Feb 2015 12:03:08 -0000
Message-ID: <96140799EAC545F68F224090E2F2E0A5@Tamar>
MIME-Version: 1.0
X-MDF-HostID: 18
X-MIME-Autoconverted: from quoted-printable to 8bit by delorie.com id t1LC3VvK017154

> > Sysinternals "ADInsight" is a 32bit only tool and, in order to work on
> > a 64bit Windows you seem to have to manually inject the DLL
> > ADInsightDll.dll (which is extracted into %TEMP%) into the target
> > (32-bit!) process.

> So, it seems ADInsight seems a non-starter - for my skill level anyway.

In case it helps you, or another reader of the list, here is a simple
program that injects a named dll into a target process.

Example of using it to examine the ldap calls for cygwin's "echo.exe":

- Compile as a 32-bit program using *32bit* cygwin (as ADInsight is a 32bit
process): g++ inject.cpp -o inject.exe
- Start ADInsight from SysInternals
- Start Windows command shell
- Invoke: inject.exe %TEMP%\ADInsightDll.dll c:\cygwin\bin\echo.exe hello

Regards,
Roger.

----- inject.cpp -----
/*
NAME
    Inject.cpp

DESCRIPTION
    Inject a DLL into another process

COPYRIGHT
    Copyright (C) 2002,2015 by Roger Orr <rogero AT howzatt DOT demon DOT co DOT uk>

    This software is distributed in the hope that it will be useful, but
    without WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

    Permission is granted to anyone to make or distribute verbatim
    copies of this software provided that the copyright notice and
    this permission notice are preserved, and that the distributor
    grants the recipient permission for further distribution as permitted
    by this notice.

    Comments and suggestions are always welcome.
    Please report bugs to rogero AT howzatt DOT demon DOT co DOT uk.

EXAMPLE
    Inject MyDll fred.exe
*/

#include <windows.h>

#include <string>
#include <iostream>

//////////////////////////////////////////////////////////////////////////
// Local functions
int CreateProcessHelper(char ** it, char ** end, HANDLE & hProcess,
    HANDLE & hThread);
int InjectDLL(std::string const &dllName, HANDLE hProcess);

//////////////////////////////////////////////////////////////////////////
int main(int argc, char **argv)
{
    if (argc < 3)
    {
        std::cerr << "Syntax: inject <dllname> <progname>" << std::endl;
        return 1;
    }

    std::string const dllName = argv[1];
    std::string const progName = argv[2];

    HANDLE hProcess = 0;
    HANDLE hThread = 0;
    if (CreateProcessHelper(argv+2, argv+argc, hProcess, hThread) != 0)
    {
        return 1;
    }

    if (InjectDLL(dllName, hProcess) != 0)
    {
        TerminateProcess(hProcess, GetLastError());
        return 1;
    }

    // resume the created process once we've loaded the DLL
    if (::ResumeThread(hThread) == (DWORD)-1)
    {
        std::cout << "ResumeThread failed with " << GetLastError()
            << std::endl;
        return 1;
    }

    DWORD ret = ::WaitForSingleObject(hProcess, INFINITE);
    if (ret == WAIT_OBJECT_0)
    {
        DWORD exitCode;
        if (GetExitCodeProcess(hProcess, &exitCode))
        {
            std::cout << "Process " << progName << " terminated: "
                 "return code: " << exitCode << std::endl;
            ret = exitCode;
        }
        else
        {
            ret = GetLastError();
            std::cout << "Process terminated: return code unavailable: "
                << ret << std::endl;
        }
    }
    else if (ret == WAIT_FAILED)
    {
        std::cout << "Process wait failed: " << GetLastError() << std::endl;
    }
    else
    {
        std::cout << "Process wait failed: " << ret << std::endl;
    }

    return ret;
}

//////////////////////////////////////////////////////////////////////////
// Inject DLL 'dllName' into process 'hProcess'
int InjectDLL(std::string const &dllName, HANDLE hProcess)
{
    LPTHREAD_START_ROUTINE lpStartAddress = 0;

    // Create memory in target process
    LPVOID const chDllName = VirtualAllocEx(hProcess, 0, dllName.size() + 1,
        MEM_COMMIT, PAGE_READWRITE);
    if (chDllName == 0)
    {
        std::cerr << "VirtualAllocEx failed: " << GetLastError()
            << std::endl;
        return 1;
    }

    // Map into my process
    if (! WriteProcessMemory(hProcess, chDllName,
        dllName.c_str(), dllName.size()+1, 0))
    {
        std::cerr << "WriteProcessMemory failed: " << GetLastError()
            << std::endl;
        return 1;
    }

    lpStartAddress = (LPTHREAD_START_ROUTINE)LoadLibrary;

    // Start a remote thread, at LoadLibraryA in the target process
    // Note we assume KERNEL32 has a fixed load address
    DWORD threadId(0);
    HANDLE const hRemoteThread = CreateRemoteThread(hProcess, 0, 0,
        lpStartAddress, chDllName, 0, &threadId);
    if (hRemoteThread == 0)
    {
        std::cerr << "CreateRemoteThread failed: " << GetLastError()
            << std::endl;
        return 1;
    }

    WaitForSingleObject(hRemoteThread, 10000);
    DWORD exitCode;
    if (! GetExitCodeThread(hRemoteThread, &exitCode))
    {
        std::cerr << "GetExitCodeThread failed: " << GetLastError()
            << std::endl;
        return 1;
    }

    if (exitCode == STILL_ACTIVE)
    {
        std::cout << "Remote thread still running..." << std::endl;
        return 1;
    }
    else if (exitCode == 0)
    {
        std::cout << "Remote thread failed to load DLL" << std::endl;
        return 1;
    }

    // Tidy up the allocated memory.
    if (! VirtualFreeEx(hProcess, chDllName, 0, MEM_RELEASE))
    {
        std::cout << "Warning: unable to free memory in target process: "
            << GetLastError() << std::endl;
    }

    return 0;
}

//////////////////////////////////////////////////////////////////////////
// Wrapper for create process.
int CreateProcessHelper(
    char ** it,
    char ** end,
    HANDLE &hProcess,
    HANDLE &hThread)
{
    char * executable = *it;

    // Search for possible executable matching the program name
    char szFullName[ MAX_PATH ];
    if (0 != SearchPath(0, executable, ".exe",
        sizeof(szFullName), szFullName, 0))
        executable = szFullName;
    
    std::string cmdLine;
    for (; it != end; ++it)
    {
        std::string curr(*it);

        if (cmdLine.length())
            cmdLine += " ";

        if (curr.find(' ') != std::string::npos)
        {
            cmdLine += '"';
            cmdLine += curr;
            cmdLine += '"';
        }
        else
        {
            cmdLine += curr;
        }
    }

    STARTUPINFO startupInfo = { sizeof(startupInfo) };
    startupInfo.dwFlags = STARTF_USESHOWWINDOW;
    startupInfo.wShowWindow = SW_SHOWNORMAL; // Assist GUI programs
    PROCESS_INFORMATION procInfo;

    if (! CreateProcess(executable, const_cast<char*>(cmdLine.c_str()),
        0, 0, TRUE, CREATE_SUSPENDED, 0, 0, &startupInfo, & procInfo))
    {
        std::cout << "CreateProcess for " << executable << " failed: "
            << GetLastError() << std::endl;
        return 1;
    }

    hProcess = procInfo.hProcess;
    hThread = procInfo.hThread;
    return 0;
}
----- ends -----



--
Problem reports:       http://cygwin.com/problems.html
FAQ:                   http://cygwin.com/faq/
Documentation:         http://cygwin.com/docs.html
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019