|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Revision 4IntroductionThe source files depend a lot on function pointers. Overview is recommended. DLL Injection is similar to 'Injecting' code into an already running process. Many things have been taken from Matt Pietrek's book 'Secrets of Windows 95'. Function interception means 'intercepting' an API function that was loaded by a statically linked DLL by modifying the address of the beginning of the function's code, resulting in the application to call your 'intercepting' function instead of the original 'intercepted' function. This is similar to the idea in "APIHijack - A Library for easy DLL function hooking" article posted by Wade Brainerd. DLL Injection"DLL Injection" is not an accurate name for what my content will actually be. My code will 'inject' a series of assembled assembly language instructions [Code] into some available space in the running process and alters the registers to point at the offset of the 'injected' [code]. The process will of course execute the instructions which will load a certain DLL, which is the DLL that is being injected. Note that this code 'Injects' [code]. The code can be anything, it doesn't necessarily have to load a DLL. Hence, the inaccurate title. There are two ways to 'Inject' a series of bytes into an already running process. (Of course, you can use One good yet slow method of injecting the code is using Windows' debugging functions. Suspend the threads of the running process (using the debugging functions) and use Lookup the MSDN library for more information (MSDN). Useful points to lookup:
Have a look at the accompanied files: Injector_src.zip. --- Google Groups - A Message board thread on Function InterceptionNotice the DLL project in the zip file. This function is in HookApi.h. // Macro for adding pointers/DWORDs together without C arithmetic interfering // -- Taken from Matt Pietrek's book // Thought it'd be great to use.. #define MakePtr( cast, ptr, addValue ) (cast)( (DWORD)(ptr)+(DWORD)(addValue)) //This code is very similar to Matt Pietrek's, except that it is written //according to my understanding... //And Matt Pietrek's also handles Win32s //--(Because they it has some sort of a problem) PROC WINAPI HookImportedFunction(HMODULE hModule, //Module to intercept calls from PSTR FunctionModule, //The dll file that contains the function you want to //hook(ex: "USER32.dll") PSTR FunctionName, //The function that you want to hook //(ex: "MessageBoxA") PROC pfnNewProc) //New function, this gets called instead { PROC pfnOriginalProc; //The intercepted function's original location IMAGE_DOS_HEADER *pDosHeader; IMAGE_NT_HEADERS *pNTHeader; IMAGE_IMPORT_DESCRIPTOR *pImportDesc; IMAGE_THUNK_DATA *pThunk; // Verify that a valid pfn was passed if ( IsBadCodePtr(pfnNewProc) ) return 0; pfnOriginalProc = GetProcAddress(GetModuleHandle(FunctionModule), FunctionName); if(!pfnOriginalProc) return 0; pDosHeader = (PIMAGE_DOS_HEADER)hModule;
//kindly read the ImgHelp function reference
//in the Image Help Library section in MSDN
//hModule is the Process's Base address (GetModuleHandle(0))
//even if called in the dll, it still gets the hModule of the calling process
//---That's you should save the hInstance of the DLL as a global variable,
//in DllMain(), because it's the only way to get it(I think)// Tests to make sure we're looking at a module image (the 'MZ' header) if ( IsBadReadPtr(pDosHeader, sizeof(IMAGE_DOS_HEADER)) ) return 0; if ( pDosHeader->e_magic != IMAGE_DOS_SIGNATURE ) //Image_DOS_SIGNATURE is a WORD (2bytes, 'M', 'Z' 's values) return 0; // The MZ header has a pointer to the PE header pNTHeader = MakePtr(PIMAGE_NT_HEADERS, pDosHeader, pDosHeader->e_lfanew); //it's like doing pDosHeader + pDosHeader->e_lfanew // e_lfanew contains a RVA to the 'PE\0\0' Header...An rva means, offset, // relative to the BaseAddress of module // -pDosHeader is the base address..and e_lfanew is the RVA, // so summing them, will give you the Virtual Address.. // More tests to make sure we're looking at a "PE" image if ( IsBadReadPtr(pNTHeader, sizeof(IMAGE_NT_HEADERS)) ) return 0; if ( pNTHeader->Signature != IMAGE_NT_SIGNATURE ) //IMAGE_NT_SIGNATURE is a DWORD (4bytes, 'P', 'E', '\0', '\0' 's values) return 0; // We now have a valid pointer to the module's PE header. // Now get a pointer to its imports section pImportDesc = MakePtr(PIMAGE_IMPORT_DESCRIPTOR, pDosHeader, //IMAGE_IMPORT_DESCRIPTOR *pImportDesc; pNTHeader->OptionalHeader.DataDirectory [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress); //What i just did was get the imports section by getting the RVA of it //(like i did above), then adding the base addr to it. //// pNTHeader->OptionalHeader.DataDirectory /// [IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress //// IMAGE_DIRECTORY_ENTRY_IMPORT==1 -- Look at that PE documentation. //// Pietrek's articles in MSJ and MSDN Magazine will be real helpful! //Go out if imports table doesn't exist if ( pImportDesc == (PIMAGE_IMPORT_DESCRIPTOR)pNTHeader ) return 0; //pImportDesc will ==pNTHeader. //if the RVA==0, cause pNTHeader+0==pNTHeader -> stored in pImportDesc //Therefore, pImportDesc==pNTHeader // Iterate through the array of imported module descriptors, looking // for the module whose name matches the FunctionModule parameter while ( pImportDesc->Name ) //Name is a DWORD (RVA, to a DLL name) { PSTR pszModName = MakePtr(PSTR, pDosHeader, pImportDesc->Name); if ( stricmp(pszModName, FunctionModule) == 0 ) //str"i"cmp,,, suggest you to ignore cases when comparing, break; //or strcmpi() in some compilers pImportDesc++; // Advance to next imported module descriptor } // Get out if we didn't find the Dll name. // pImportDesc->Name will be non-zero if we found it. if ( pImportDesc->Name == 0 ) return 0; // Get a pointer to the found module's import address table (IAT) // =====IMAGE_THUNK_DATA *pThunk; pThunk = MakePtr(PIMAGE_THUNK_DATA, pDosHeader, pImportDesc->FirstThunk); //This is what i was talkin about earlier... //In pThunk, if it was image loaded in memory, you'll get the address to //entry point of functions //but in a disk file, It's a function name // Look through the table of import addresses, of the found // DLL, looking for the function's entry point that matches // the address we got back from GetProcAddress above. while ( pThunk->u1.Function ) { if ( (DWORD)pThunk->u1.Function == (DWORD)pfnOriginalProc ) { // We found it! Overwrite the original address with the // address of the interception function. Return the original // address to the caller so that they can chain on to it. pThunk->u1.Function = (PDWORD)pfnNewProc; // pfnNewProc is in the parameters of the function //pfnOriginalProc = (PROC)(DWORD)pdw1; return pfnOriginalProc; } pThunk++; // Advance to next imported function address } return 0; //function not found!!!!! } Also notice:
They are the functions to write to the LOG file. What the whole project does is inject a DLL into an already running process (mIRC.exe - mIRC chatting program (mIRC)) [in my case]. It then creates a Log file of all the intercepted Winsock functions. Have a look at Successlog.txt. It is highly recommended that you apply the program on mIRC only, since it has been created for it. Have fun coding your own :) I think you got the idea. I hope this is useful. Regards, CrankHank Nasser R. Rowhani - nrowhani9@hotmail.com
|
||||||||||||||||||||||