Utilice urgentemente vc6 para crear un programa de selección de palabras con el mouse, ¡gracias a todas las personas de buen corazón!
Mi método incluye los siguientes tres pasos:
Primero, obtenga la posición actual del mouse a través de SetWindowsHookEx.
En segundo lugar, envíe información de redibujo a la ventana debajo del mouse, para que llame a la función del sistema para volver a dibujar.
Implementado a través de WindowFromPoint, ScreenToClient e InvalidateRect.
En tercer lugar, intercepte las llamadas a funciones del sistema y obtenga parámetros (tome TextOutA como ejemplo)
1. Modele su propia función MyTextOutA después de TextOutA, con los mismos parámetros y valores de retorno que TextOutA. Colóquelo en la DLL donde se encuentra el enlace del sistema.
SysFunc1=(DWORD)GetProcAddress(GetModuleHandle("gdi32.dll"), "TextOutA");
BOOL WINAPI MyTextOutA(HDC hdc, int nXStart, int nYStart, LPCSTR lpszString , int cbString)
{ //Procesamiento de lpszString de salida
return ((FARPROC)SysFunc1)(hdc, nXStart, nYStart, lpszString, cbString);}
2.
2. Dado que el gancho del mouse del sistema ya completó el trabajo de inyectar otros procesos GUI, no necesitamos realizar más trabajos de inyección.
Si sabe que todas las funciones de enlace del sistema deben estar en bibliotecas dinámicas, no le sorprenderá la "inyección". Cuando un proceso llama implícita o explícitamente a una función en una biblioteca de enlaces dinámicos, el sistema asignará la biblioteca de enlaces dinámicos al espacio de direcciones virtuales del proceso (en lo sucesivo, "espacio de direcciones"). Esto hace que la biblioteca de vínculos dinámicos forme parte del proceso, se ejecuta como el proceso y utiliza la pila del proceso (consulte la Figura 1).
Figura 1 DLL asignada al espacio de direcciones virtuales
Para los enlaces del sistema, el sistema asignará automáticamente la DLL que contiene la "función de devolución de llamada del enlace" a las direcciones de todos los procesos afectados por el enlace. función espacio, es decir, la DLL se inyecta en estos procesos.
3. Cuando la DLL que contiene el gancho se inyecta en otro proceso, busca la dirección base del módulo (EXE y DLL) asignada a la memoria virtual del proceso. Sus direcciones base las determina el vinculador en el momento del enlace. Al crear un nuevo proyecto Win32, el vinculador VC utiliza una dirección base predeterminada de 0x00400000, pero esto se puede cambiar mediante la opción BASE del vinculador. Los EXE generalmente se asignan a 0x00400000 en la memoria virtual, mientras que las DLL tienen diferentes direcciones base y generalmente se asignan al mismo espacio de direcciones virtuales de diferentes procesos.
¿Cómo saber dónde están mapeados EXE y DLL?
En Win32, HMODULE y HINSTANCE son iguales. Son las direcciones base del espacio de memoria virtual donde se cargan los módulos correspondientes al proceso.
Por ejemplo
HMODULE hmodule=GetModuleHandle(〃gdi32.dll〃);
El identificador del módulo devuelto se convierte en un puntero, que es la dirección base del proceso que cargó gdi32. dll. )
ChangeFuncEntry((DWORD)mbi.BaseAddress, 1);
base=(DWORD)mbi.BaseAddress mbi.RegionSize; /p>
4. Obtenga la dirección base del módulo de acuerdo con el formato del archivo PE y verifique la matriz IMAGE-IMPORT-DEscriptOR del módulo para ver si se introduce gdi32.dll. Si es así, agote la matriz IMAGE-THUNK-DATA para ver si se introduce la función TextOutA.
5. Si lo encuentra, reemplácelo con su propia función.
El sistema asigna EXE y DLL al espacio de memoria virtual, y su estructura en la memoria es la misma que la estructura de archivos estáticos en el disco. Este es el formato de archivo PE (Portable Executable).
Todas las llamadas a una función API determinada siempre se transfieren a través de la misma ubicación en el archivo ejecutable. Esta es la tabla de direcciones de importación para el módulo (que puede ser un EXE o DLL). Aquí están todos los nombres de funciones y direcciones de otras DLL llamadas por el módulo. Las llamadas a funciones a otras DLL en realidad simplemente saltan a la tabla de direcciones de importación y luego a la entrada de función real de la DLL. Por ejemplo:
Figura 2 La llamada a MessageBox() saltará a la tabla de direcciones de entrada y luego saltará a la función MessageBox
IMAGE-IMPORT-DEscriptOR e IMAGE -THUNK- DATOS respectivamente Corresponde a DLL y funciones. Su formato es el mismo que el de la tabla de direcciones de entrada del archivo PE (consulte winnt.h para conocer la estructura de datos).
BOOL ChangeFuncEntry(HMODULE hmodule)
{ PIMAGE-DOS-HEADER pDOSHeader
PIMAGE-NT -HEADERS pNTHeader
PIMAGE; -IMPORT-DEscriptOR pImportDesc;
/ Obtener funciones del sistema y la entrada de mis funciones /
pSysFunc1=(DWORD)GetProcAddress(GetModuleHandle(〃gdi32.dll〃),〃TextOutA〃)
pMyFunc1= (DWORD) GetProcAddress(GetModuleHandle(〃hookdll.dll〃), 〃MyTextOutA〃;
pDOSHeader=(PIMAGE-DOS-HEADER)hmodule;
if (IsBadReadPtr(hmodule, sizeof(PIMAGE-NT-HEADERS)))
return FALSE
if (pDOSHeader ->e-magic! = IMAGEN-DOS-SIGNATURE)
Devuelve FALSO
pNTHeader=(PIMAGE-NT-HEADERS) ((DWORD)pDOSHeader (DWORD)pDOSHeader-〉-e-lfanew);
Si (pNTHeader-〉Firma!= IMAGEN-NT-FIRMA)
Devuelve FALSO
pImportDesc = (PIMAGE-IMPORT-〉DEscriptOR); /p>
if (pNTHeader-〉Firma !DEscriptOR)((DWORD)hmodule+(DWORD)pNTHeader-〉OptionalHeader.DataDirectory
[IMAGE-DIRECTORY -ENTRY-IMPORT].VirtualAddress); /p>
If (pImportDesc == (PIMAGE-IMPORT-DEscriptOR) pNTHeader)
Devuelve FALSE
while (pImportDesc-〉Nombre)
{ PIMAGE-THUNK-DATA pThunk;
strcpy(buffer, (char )((DWORD)hmodule (DWORD)pImportDesc->Name)); //p>
CharLower (búfer);
if(strcmp(búfer, "gdi32.dll"))
{ pImportDesc
continuar; }else
{ pThunk=(PIMAGE-THUNK-DATA)((DWORD) hmodule (DWORD)pImportDesc
-〉FirstThunk);//p>
while (pThunk-〉u1.Function)//p>
{ if ((pThunk-〉 u1.Function) == pSysFunc1 )
{ VirtualProtect((LPVOID)(pThunk-〉u1.Function),
sizeof(DWORD), PAGE- EXECUTE-READWRITE, &dwProtect
(pThunk-〉u1.
(pThunk-〉u1.Function)=pMyFunc1;
VirtualProtect((LPVOID)(&pThunk -〉u1.Function), sizeof(DWORD) , dwProtect, temp); }
pThunk; } Return 1; }}}
Después de reemplazar la entrada de TextOutA en la tabla InputAddress con MyTextOutA, la función del sistema llama a la parte principal. del trabajo de interceptación Se ha completado. Cuando el proceso de inyección llama a TextOutA, en realidad llama a MyTextOutA. Solo necesita mostrar la cadena entrante en MyTextOutA y luego entregársela a TextOutA para su procesamiento.