Thread: .DLL works in win2K but not XP

  1. #1
    Frustrated Programmer :( phantom's Avatar
    Join Date
    Sep 2001
    Posts
    163

    .DLL works in win2K but not XP

    PLEASE NOTE - The code works on most computers but NOT MINE! So please don't respond to this thread with 'it works on my computer'.

    I have been using the following code over the last two years and it worked fine on my Win2K computer; In February my computer crashed and I decided to upgrade to Win XP, this code now no longer works.

    Please note that while I did not program the following code (beyond my capabilities) I own copyright to it.

    My computer is Windows XP professional service pack 3 - fully updated. Again - this code DOES NOT work on my computer.

    This code hooks information out of a thrid party program (this does not violate any copyright, it only gets the information that is visible to the user) and puts it into a database along with my decisions.
    If anyone understands this code then I am happy to send them the full Visual C++ 6.0 workspace.

    Code:
    // GDIHook.cpp : Defines the entry point for the DLL application.
    //
    
    #include "stdafx.h"
    
    #include <tchar.h>
    #include <stdio.h>
    #include <Psapi.h>
    
    HMODULE g_hMod;
    FILE *fp;
    
    enum statData
    {
    	None = -1,
    	Players=0,
    	PlayerPos,
    	Win_Odds,
    	Pot_odds
    };
    
    bool bPlayer = false;
    bool bPatchOn = true;
    
    char g_szString[100] = {0};
    
    class CData
    {
    public:
    	CData ()
    	{
    		strcpy(szPlayers, " ");
    		strcpy(szPlayerPos, " ");
    		strcpy(szWin_Odds, "0%");
    		strcpy(szPot_odds, "0%");
    	}
    
    	char szPlayers[10];
    	char szPlayerPos[10];
    	char szWin_Odds[10];
    	char szPot_odds[10];
    	
    	char* GetString();
    };
    
    char* CData::GetString()
    {
    	ZeroMemory(g_szString, 100);
    	if(bPlayer)
    	{
    		strcpy(g_szString, "F,");
    	}
    	else
    	{
    		strcpy(g_szString, "P,");
    	}
    
    	strcat(g_szString, szPlayers);
    	strcat(g_szString, ",");
    	strcat(g_szString, szPlayerPos);
    	strcat(g_szString, ",");
    	strcat(g_szString, szWin_Odds);
    	strcat(g_szString, ",");
    	strcat(g_szString, szPot_odds);
    	strcat(g_szString, ",\r\n");
    	
    
    	return g_szString;
    }
    
    static CData g_Data;
    
    ///////////////////////////////////////////////////////////////////////
    // PutOnClipboard
    ///////////////////////////////////////////////////////////////////////
    
    BOOL WINAPI PutOnClipboard(char *data) 
    { 
        LPTSTR  lptstrCopy; 
        HGLOBAL hglbCopy; 
    	
        // Open the clipboard, and empty it. 
    	
        if (!OpenClipboard(NULL)) 
            return FALSE; 
    
        // If no data, return
    	if (strlen(data) == 0)	
        {   
            CloseClipboard();                   // selection 
            return FALSE; 
        } 
    		
        hglbCopy = GlobalAlloc(GMEM_MOVEABLE, (strlen(data) + 1) * sizeof(TCHAR)); 
        if (hglbCopy == NULL) 
        { 
            CloseClipboard(); 
            return FALSE; 
        } 
    		
        // Lock the handle and copy the text to the buffer. 
    		
        lptstrCopy = (char *) GlobalLock(hglbCopy); 
    	strcpy(lptstrCopy, data);
        GlobalUnlock(hglbCopy); 
    		
        // Place the handle on the clipboard. 
    
    	EmptyClipboard(); 
        SetClipboardData(CF_TEXT, hglbCopy); 
    	CloseClipboard();
    
    	return TRUE;
    }
    
    ///////////////////////////////////////////////////////////////////////
    // FilterData
    ///////////////////////////////////////////////////////////////////////
    
    int FilterData(int x, int y)
    {
    MessageBox(0, "Checking for info", 0, MB_OK);
    	if (x == 461 && y == 24)
    	{
    //		if(bPlayer)
    			return Players;
    	}
    	else if (x== 563 && y ==24)
    	{
    //		if(bPlayer)
    			return PlayerPos;
    	}
    	else if (x >= 440 && x<= 465 && y>60)
    	{
    //		if(bPlayer)
    			return Win_Odds;
    	}
    	else if (x >= 518 && x<= 570 && y>60)
    	{
    //		if(bPlayer)
    			return Pot_odds;
    	}
    	return None;
    }
    
    ///////////////////////////////////////////////////////////////////////
    // myTextOutW
    ///////////////////////////////////////////////////////////////////////
    
    BOOL WINAPI myTextOutW(HDC hDC, int x, int y, LPCWSTR str, int len)
    {
    	int iFilter = FilterData(x, y);
    	if(len >0)
    	{
    		char *pstr =(char *)LocalAlloc(LMEM_FIXED, len*2+1);
    		int len2 =WideCharToMultiByte(CP_ACP, 0, str, len, pstr, len*2, NULL, NULL);
    		pstr[len2] =0;
    		
    		if (!strcmp(pstr,"Position:"))
    				bPlayer = true;
    
    		if (!strcmp(pstr,"Group:"))
    		{
     				bPlayer = false;
    
    				strcpy(g_Data.szPlayers, " ");
    				strcpy(g_Data.szPlayerPos, " ");
    				strcpy(g_Data.szPot_odds, "0%");
    				strcpy(g_Data.szWin_Odds, "0%");
    		}
    
    		switch(iFilter)
    		{
    		case Players:
    			{
    				strcpy(g_Data.szPlayers, pstr);
    			}
    			break;
    		case PlayerPos:
    			{
    				strcpy(g_Data.szPlayerPos, pstr);
    			}
    			break;
    		case Pot_odds:
    			{
    				strcpy(g_Data.szPot_odds, pstr);
    			}
    			break;
    		case Win_Odds:
    			{
    				strcpy(g_Data.szWin_Odds, pstr);
    			}
    			break;
    		default:;
    			// nothing
    		}
    //		fprintf(fp, "\nmyTextOutW X=%d, Y=%d, String = %s\n",  x, y, pstr);
    //		fflush(fp);
    		
    		char *szData = g_Data.GetString();
    		PutOnClipboard(szData);
    		fprintf(fp, szData);
    		fflush(fp);
    
    		LocalFree(pstr);
    	}
    	else
    	{
    		switch(iFilter)
    		{
    		case Players:
    			{
    				strcpy(g_Data.szPlayers, " ");
    			}
    			break;
    		case PlayerPos:
    			{
    				strcpy(g_Data.szPlayerPos, " ");
    			}
    			break;
    		case Pot_odds:
    			{
    				strcpy(g_Data.szPot_odds, "0%");
    			}
    			break;
    		case Win_Odds:
    			{
    				strcpy(g_Data.szWin_Odds, "0%");
    			}
    			break;
    		default:;
    			// nothing
    		}
    	}
    
    	return TextOutW(hDC, x, y, str, len);
    }
    
    ///////////////////////////////////////////////////////////////////////
    // patchEAT
    ///////////////////////////////////////////////////////////////////////
    
    DWORD WINAPI patchEAT(HMODULE hMod, PROC origFunc, PROC newFunc)
    {
    	PIMAGE_DOS_HEADER pDosH;
    	PIMAGE_NT_HEADERS pNTH;
    	PIMAGE_EXPORT_DIRECTORY pExportDir;
    	
    	pDosH = (PIMAGE_DOS_HEADER) hMod;
    	pNTH = (PIMAGE_NT_HEADERS) ((DWORD) pDosH + (DWORD) pDosH->e_lfanew);
    	pExportDir = (PIMAGE_EXPORT_DIRECTORY) ((DWORD) pDosH + 
    		(DWORD) (pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress));
    	
    	ULONG *arrSymbols = (ULONG *) ((DWORD) pDosH + pExportDir->AddressOfFunctions);
    	for(unsigned int i = 0; i < pExportDir->NumberOfFunctions; ++i)
    	{
    		DWORD *pFuncRVA = (DWORD *) &arrSymbols[i];
    		DWORD origRVA = (DWORD) origFunc - (DWORD) pDosH;
    		if(*pFuncRVA == origRVA)
    		{
    			MEMORY_BASIC_INFORMATION mbi;
    			DWORD oldProt;
    			VirtualQuery(pFuncRVA, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    			VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &oldProt);
    			*pFuncRVA = (DWORD) newFunc - (DWORD) pDosH;
    			VirtualProtect(mbi.BaseAddress, mbi.RegionSize, oldProt, &oldProt);
    			
    			break;
    		}
    	}
    	
    	return 0;
    }
    
    ///////////////////////////////////////////////////////////////////////
    // patchIAT
    ///////////////////////////////////////////////////////////////////////
     
    DWORD WINAPI patchIAT(HMODULE hMod, PROC origFunc, PROC newFunc)
    {
    	PIMAGE_DOS_HEADER pDosH;
    	PIMAGE_NT_HEADERS pNTH;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc;
    	PIMAGE_THUNK_DATA pThunk;
    	
    	if(!newFunc || !hMod || hMod == g_hMod)
    		return 0;
    	
    	// Verify that the newFunc is valid
    	if(IsBadCodePtr(newFunc))
    		return 0;
    	
    	// Get DOS Header
    	pDosH = (PIMAGE_DOS_HEADER) hMod;
    	
    	// Verify that the PE is valid by checking e_magic's value and DOS Header size
    	if(IsBadReadPtr(pDosH, sizeof(IMAGE_DOS_HEADER)))
    		return 0;
    	
    	if(pDosH->e_magic != IMAGE_DOS_SIGNATURE)
    		return 0;
    	
    	// Find the NT Header by using the offset of e_lfanew value from hMod
    	pNTH = (PIMAGE_NT_HEADERS) ((DWORD) pDosH + (DWORD) pDosH->e_lfanew);
    	
    	// Verify that the NT Header is correct
    	if(IsBadReadPtr(pNTH, sizeof(IMAGE_NT_HEADERS)))
    		return 0;
    	
    	if(pNTH->Signature != IMAGE_NT_SIGNATURE)
    		return 0;
    	
    	// iat patching
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD) pDosH + 
    		(DWORD) (pNTH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
    	
    	if(pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR) pNTH)
    		return 0;
    	
    	while(pImportDesc->Name)
    	{
    		// pImportDesc->Name gives the name of the module, so we can find "gdi32.dll"
    		char *name = (char *) ((DWORD) pDosH + (DWORD) (pImportDesc->Name));
    		// stricmp returns 0 if strings are equal, case insensitive
    
    		if(name && _stricmp(name, "gdi32.dll") == 0)
    		{
    			pThunk = (PIMAGE_THUNK_DATA)((DWORD) pDosH + (DWORD) pImportDesc->FirstThunk);
    			while(pThunk && pThunk->u1.Function)
    			{
    				// get the pointer of the imported function and see if it matches up with the original 
    				if((DWORD) pThunk->u1.Function == (DWORD) origFunc)
    				{
    					//Sleep(250);
    					MEMORY_BASIC_INFORMATION mbi;
    					DWORD oldProt;
    
    					VirtualQuery(&pThunk->u1.Function, &mbi, sizeof(MEMORY_BASIC_INFORMATION));
    					VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &oldProt);
    					//pThunk->u1.Function = (& DWORD) newFunc;  //Note that this is the original line
    					pThunk->u1.Function = (DWORD *) newFunc;
    					VirtualProtect(mbi.BaseAddress, mbi.RegionSize, oldProt, &oldProt);
    					break;
    				}
    				else
    				{
    					++pThunk;
    				}
    			}
    		}
    //		Sleep(250);
    		++pImportDesc;
    	}
    
    	return 0;	
    }
    
    ///////////////////////////////////////////////////////////////////////
    // setHook
    ///////////////////////////////////////////////////////////////////////
    
    PROC setHook()
    {
    	fp = fopen("C:\\stats.txt", "w");
    	
    	HMODULE gdi32 = LoadLibrary("gdi32.dll");
    	
    	/* initialize all the original functions to be hooked */
    	FARPROC origTextOutW = GetProcAddress(gdi32, "TextOutW");
    
    	HMODULE hMods[1024];
    	DWORD cbNeeded;
    
    	HANDLE hProcess = GetCurrentProcess();
    	
    	if(EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
    	{
    		patchEAT(gdi32, (PROC) origTextOutW, (PROC) myTextOutW);
    
    		for (unsigned int i = 0; i < (cbNeeded / sizeof(HMODULE)); ++i)
    		{
    			if(hMods[i] != g_hMod && i != 29)
    			{
     				patchIAT(hMods[i], (PROC) origTextOutW, (PROC) myTextOutW);
    			}
    		}
    	}
    
    	bPatchOn = false;
    	return 0;
    }
    
    ///////////////////////////////////////////////////////////////////////
    // DllMain
    ///////////////////////////////////////////////////////////////////////
     
    extern "C" BOOL APIENTRY WINAPI DllMain( HANDLE hInst, DWORD reason, LPVOID lpReserved )
    {
    	switch(reason)
    	{
    	case DLL_PROCESS_ATTACH:
    		{
    			g_hMod = (HMODULE) hInst;
    			CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) setHook, 0, 0, NULL);
    		}
    		break;
    
    	case DLL_PROCESS_DETACH:
    		{
    			fclose(fp);
    		}
    		break;
    	}
    	
        return TRUE;
    }
    My site to register for all my other websites!
    'Clifton Bazaar'

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    "It doesn't work" doesn't tell me anything. WHAT happens?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    looking at your code I suppose you are trying to read/write some memory in the module import table.

    in XP this region is read/write protected... so you need to modify your process rights before accessing this memory I cannot recall the exact function name for this
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    By the way, doing this hooking manually is usually just a big waste of time. Go download Detours from Microsoft. Not only does it provide function hooking in a way that works on ALL Windows platforms, it allows you to hook at the instruction level, not just the function level.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    You already started a thread for this on the Windows forum.
    Code works in Win2K but not XP

  6. #6
    Frustrated Programmer :( phantom's Avatar
    Join Date
    Sep 2001
    Posts
    163
    Quote Originally Posted by brewbuck View Post
    "It doesn't work" doesn't tell me anything. WHAT happens?
    Sorry I should have been more specific - the code is supposed to put the data onto the microsoft clipboard, which it did in win2K, but under windows XP nothing appears on the clipboard.
    The DLL is being loaded and put into memory (it is running) but it doesn't hook any info.

    You already started a thread for this on the Windows forum.
    Sorry

    looking at your code I suppose you are trying to read/write some memory in the module import table.

    in XP this region is read/write protected... so you need to modify your process rights before accessing this memory I cannot recall the exact function name for this
    If someone can remember the function name I'll go and work out how to use it.

    By the way, doing this hooking manually is usually just a big waste of time. Go download Detours from Microsoft. Not only does it provide function hooking in a way that works on ALL Windows platforms, it allows you to hook at the instruction level, not just the function level.
    Reading it now.

    This code does not work under Windows 7 either I have found out ten minutes ago
    Last edited by phantom; 04-05-2010 at 06:41 PM. Reason: Windows 7 update
    My site to register for all my other websites!
    'Clifton Bazaar'

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    I have looked through my working code of hooking the entries in the dll. There are some differences...

    so here is some shortcuts from my working code - hope you can find something useful here

    Code:
    #include <Dbghelp.h>
    typedef
    int
    (WSAAPI * LPFN_SENDTO)(
    					   SOCKET s,
    					   const char FAR * buf,
    					   int len,
    					   int flags,
    					   const struct sockaddr FAR * to,
    					   int tolen
    					   );
    	LPFN_SENDTO					pSendTo;
    
    static int WSAAPI MySendTo ( SOCKET s, 
    								  const char FAR * buf, 
    								  int len, 
    								  int flags, 
    								  const struct sockaddr FAR * to, 
    								  int tolen )
    {
    	/* do something */
    	
    	return res;
    }
    
    
    /*
     *	Static functions
     */
    static void ReplaceIATEntryInOneMod(PCSTR pszCalleeModName,
    							 PROC pfnCurrent,
    							 PROC pfnNew,
    							 HMODULE hmodCaller)
    {
    	ULONG ulSize = 0;
    	PIMAGE_THUNK_DATA pThunk;
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc = NULL;
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)
    		ImageDirectoryEntryToData(hmodCaller, TRUE,
    		IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);
     			
    	if(pImportDesc == NULL)
    	{
    		
    		return; //in this module there is no import directory;
    	}
    	//Let's find descriptor of the callee module
    	for(;pImportDesc->Name;pImportDesc++)
    	{
    		PSTR pszModName = (PSTR)((PBYTE)hmodCaller + pImportDesc->Name);
    		if(lstrcmpiA(pszModName,pszCalleeModName)== 0)
    			break;
    	}
    	if(pImportDesc->Name == 0)
    	{
    		//there is no imports from the callee module
    		return;
    	}
    	//Let's get the Import Address Table (IAT) for the functions from the callee Module
    	pThunk = (PIMAGE_THUNK_DATA)
    		((PBYTE)hmodCaller + pImportDesc->FirstThunk);
    
    	//Lets replace the function address
    	for(;pThunk->u1.Function;pThunk++)
    	{
    		//What's the address of the current function
    		PROC* ppfn = (PROC*)&pThunk->u1.Function;
    
    		//Is the address correct?
    		BOOL fFound = (*ppfn == pfnCurrent);
    		
    		if(fFound)
    		{
    			//The address is correct - lets replace the function
    			DWORD dummy;
    			//to open access to the desired memory location before write
    			BOOL res = VirtualProtect(ppfn,sizeof(ppfn),PAGE_EXECUTE_READWRITE,&dummy);
    			res = WriteProcessMemory(GetCurrentProcess(),ppfn,&pfnNew,sizeof(pfnNew),NULL);
    			
    			return; //finished OK
    		}
    	}
    
    	//The required function is not found
    }
    
    
    
    int SetHook(void)
    {
    	HMODULE hmodCaller = GetModuleHandle(NULL);
    	HMODULE hModCallee = GetModuleHandle("Ws2_32");
    		
    	pSendTo = (LPFN_SENDTO)GetProcAddress(hModCallee,"sendto");
    	
    	ReplaceIATEntryInOneMod("Ws2_32.dll",(PROC)pSendTo,(PROC)MySendTo,hmodCaller);
    	return 0;
    }
    
    int UnHook()
    {
    	HMODULE hmodCaller = GetModuleHandle(NULL);
    	ReplaceIATEntryInOneMod("Ws2_32.dll",(PROC)MySendTo,(PROC)pSendTo,hmodCaller);
    	return 0;
    }
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    Frustrated Programmer :( phantom's Avatar
    Join Date
    Sep 2001
    Posts
    163
    I have worked out that it is not the program that is the problem but the memory protection of Windows XP - I'll transfer this conversation back to Code works in Win2K but not XP

    And to the admin - sorry about opening two topics on this.
    My site to register for all my other websites!
    'Clifton Bazaar'

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Dual Booting Win XP & Win 98
    By netboy in forum Tech Board
    Replies: 2
    Last Post: 08-18-2003, 02:29 AM
  2. Windows XP regression over time
    By DavidP in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 12-17-2002, 10:49 AM
  3. Anybody know a hardrive defragmenter that Actually works for XP?
    By incognito in forum A Brief History of Cprogramming.com
    Replies: 17
    Last Post: 05-24-2002, 10:34 AM
  4. Replies: 6
    Last Post: 01-07-2002, 02:46 AM
  5. Networking with XP Pro
    By oskilian in forum A Brief History of Cprogramming.com
    Replies: 11
    Last Post: 12-09-2001, 04:31 PM

Tags for this Thread