Есть книжка "Ассемблер и дизассемблирование" Пирогова, там в приложении еще одно подобие, но выводит импорт, экспорт, ресурсы и отладочную информацию, вобщем вот сурс - http://slil.ru/26553218
1) вызываете функцию CreateToolhelp32Snapshot, затем Process32First, Process32Next (так же следует вызыввать Module32First/Next для получения списка модулей в процессе) пока не закончаться процессы 2)читаете из структуры PROCESSENTRY32 поле szExeFile. Маппите исп. модуль себе и работаете с импортом/экспортом. Второй вариант - можно так же прочесть поле MODULEENTRY32 modBaseAddr - получить базу загрузки модуля и modBaseSize - его размер. Скопировать себе с помощью ReadProcessMemory и п.3. 3) а далее работать с директорией экспорта/импорта. хорошо расписано тут http://www.wasm.ru/article.php?article=green2red02#_Toc100906487
0x0c0de, спасиб. Вроде бы все так и делал.... только вот выдает ошибку доступа ("процесс уже занят") или как-то так... Будем искать ошибку.
Если в CreateFile передавать szExeFile, то получаю: побороть это пока не удалось... P.S. пытался через OpenFileMapping: Code: OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, "calc");
Я хз как вы там писали Code: // toolhelp.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include <windows.h> #include <Tlhelp32.h> #include <ntdll.h> #pragma comment (lib,"ntdll.lib"); VOID SetNeededPrivelege(VOID) { HANDLE hndl; TOKEN_PRIVILEGES newpriv,prevpriv; DWORD retl; if(OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hndl)) { if (LookupPrivilegeValue(0, L"SeDebugPrivilege", &newpriv.Privileges[0].Luid)) { newpriv.PrivilegeCount = 1; newpriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hndl, 0, &newpriv, sizeof(newpriv), &prevpriv, &retl); } CloseHandle(hndl); } } int _tmain(int argc, _TCHAR* argv[]) { HANDLE hSnap,hFile,hMSnp; PROCESSENTRY32 proc32; MODULEENTRY32 moduleentry32; NTSTATUS status; OBJECT_ATTRIBUTES ObjAttr; UNICODE_STRING usExeModName; IO_STATUS_BLOCK ioStatus; WCHAR wcPath[500]; SetNeededPrivelege(); hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0); if( hSnap != INVALID_HANDLE_VALUE ) { proc32.dwSize = sizeof(PROCESSENTRY32); if( Process32First( hSnap, &proc32 ) ) { do { hMSnp = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE,proc32.th32ProcessID); if(hMSnp!=INVALID_HANDLE_VALUE) { moduleentry32.dwSize = sizeof( MODULEENTRY32 ); if(Module32First(hMSnp, &moduleentry32)) { do{ if(lstrcmp(moduleentry32.szModule,proc32.szExeFile)==0) { memset(wcPath,0,500*2); if(!((_wcsnicmp(moduleentry32.szExePath, L"\\??\\", lstrlen(L"\\??\\")) == 0)|| (_wcsnicmp(moduleentry32.szExePath, L"\\SystemRoot\\", lstrlen(L"\\SystemRoot\\")) == 0) )) { lstrcpy(wcPath,L"\\??\\"); lstrcat(wcPath,moduleentry32.szExePath); }else { lstrcpy(wcPath,moduleentry32.szExePath); } RtlInitUnicodeString(&usExeModName,wcPath); InitializeObjectAttributes(&ObjAttr, &usExeModName, OBJ_CASE_INSENSITIVE, NULL, NULL); status = NtCreateFile(&hFile, FILE_READ_DATA, &ObjAttr, &ioStatus, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_WRITE|FILE_SHARE_READ, FILE_OPEN, FILE_NON_DIRECTORY_FILE, NULL, 0); if (NT_SUCCESS(status)) { wprintf(L"File %ws opened successfully\n", wcPath); wprintf(L" file size = %d bytes\n",GetFileSize(hFile,0)); NtClose(hFile); }else { wprintf(L"Cannot open file %ws status = %X\n", wcPath, status); } } }while( Module32Next(hMSnp, &moduleentry32)); } } }while(Process32Next(hSnap, &proc32)); } } Sleep(-1); return 0; } Проверка конечно довольно ненадежная [если нет \SystemRoot\ или \??\ вначале добавляем \??\], но если вам надо разберетесь и доделаете
И сейчас проблемы? Мэппите потом, после того как хендл получили xpsp2 xpsp3 vista win7 Я вообще-то тестирую код, перед тем как постить
Усе сделалось Проблема была в правах доступа к файлу. Я ж не сказал, что ваш код не рабочий Мои глюки и мои ошибки
Есть файл trigraph.exe, Builder'овский. Так вот все PE-редакторы/вьюверы сообщают, что это не PE-файл. Проверьте плиз кто-нить этот файл, чем он отличается от других. З.Ы. я у всех файлов проверяю IMAGE_DOS_SIGNATURE и IMAGE_NT_SIGNATURE. З.З.Ы. файл чист, вот отчет:
Сделал проверку таким вот образом: Code: if(PEh->Signature != IMAGE_NT_SIGNATURE) return; получаю экзепшн... З.Ы. магнитные бури что-ли сегодня...голова не пашет =\
поместите свой код в try-блок или проверяйте не выходит ли за границы выделенной под проекцию области памяти значение (смещение предположительного pe-заголовка+4+адрес начала проекции). Здесь как раз выход за границы имеет место быть (смотрела в файле trigraph.exe). 00005000 - выделено под проекцию 00010000 - смещение предполагаемого pe-заголовка
0x0c0de, спасибо. Все работает P.S. 2 x0man, я сюда не из-за плюсиков/звездочек пришел. Они мне вобще "параллельны" =)
Доброго времени суток! На rsdn есть статья, сделал все как там написано. Скомпилил dll-ку "перехватчик", затем написал прогу: Code: #include <windows.h> int main(int argc, char* argv[]) { LoadLibrary("C:\\test.dll"); MessageBox(NULL, "Test", "test", MB_OK); return 0; } Вылетает экзепшн. Подскажите плиз где ошибка? P.S. вот исходник дллки: Code: // dll.cpp : Defines the entry point for the DLL application. // #include "stdafx.h" #include <windows.h> #include "dll.h" void IntFunc(void); BOOL WINAPI NewMessage(HWND hwnd, char *text, char *hdr, UINT utype); #pragma pack(push, 1) struct jmp_far { BYTE instr_push; DWORD arg; BYTE instr_ret; }; #pragma pack(pop) BYTE old[6]; DWORD adr_MessageBoxA; DWORD written; jmp_far jump; BOOL WINAPI Intercept_MessageBoxA(HWND hwnd, char *text, char *hdr, UINT utype) { //Сначала восстанавливаем 6 первых байт функции. Это не обязательное // действие, просто мы решили подшутить над пользователем, и все // сообщения функции MessageBoxA переделать на свои, поэтому нам придется // вызвать оригинальную функцию, а для этого следует восстановить ее адрес: WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA, (void*)&old, 6, &written); //Здесь вы можете порезвиться от души и выполнить любые, пришедшие вам // в голову действия. Мы просто заменили сообщение функции на свое: char *str = "Hi From MessageBOX!!!!"; //Вызываем оригинальную функцию через указатель ((BOOL (__stdcall*)(HWND, char*, char*, UINT))adr_MessageBoxA)(hwnd, str, hdr, utype); //Снова заменяем 6 байт функции на команду перехода на нашу функцию WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA, (void*)&jump, 6,&written); return TRUE; } void InterceptFunctions(void) { DWORD op; //сначала получим абсолютный адрес функции для перехвата adr_MessageBoxA = (DWORD)GetProcAddress(GetModuleHandle("user32.dll"), "MessageBoxA"); if(adr_MessageBoxA == 0) { MessageBox(NULL, "Can`t get adr_MessageBoxA", "Error!", 0); return; } // Зададим машинный код инструкции перехода, который затем впишем // в начало полученного адреса: jump.instr_push = 0x68; jump.arg = (DWORD)&Intercept_MessageBoxA; jump.instr_ret = 0xC3; //Прочитаем и сохраним первые оригинальные 6 байт стандартной API функции ReadProcessMemory(GetCurrentProcess(),(void*) adr_MessageBoxA, (void*)&old, 6, &written); //Запишем команду перехода на нашу функцию поверх этих 6-ти байт WriteProcessMemory(GetCurrentProcess(), (void*)adr_MessageBoxA, (void*)&jump, sizeof(jmp_far), &written); } BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { if(ul_reason_for_call == DLL_PROCESS_ATTACH ) { InterceptFunctions(); } return TRUE; }
Мне кажется или в этом коде нет функции VirtualProtectEx ? --added Кстати вот была тема http://forum.antichat.ru/thread32176.html А, сейчас посмотрела код WriteProcessMemory Code: 7C80222C 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 7C80222F 8D45 14 LEA EAX,DWORD PTR SS:[EBP+14] 7C802232 50 PUSH EAX 7C802233 6A 40 PUSH 40 7C802235 8D45 FC LEA EAX,DWORD PTR SS:[EBP-4] 7C802238 50 PUSH EAX 7C802239 8D45 F8 LEA EAX,DWORD PTR SS:[EBP-8] 7C80223C 50 PUSH EAX 7C80223D 57 PUSH EDI 7C80223E 895D FC MOV DWORD PTR SS:[EBP-4],EBX 7C802241 FFD6 CALL ESI ; ntdll.ZwProtectVirtualMemory VirtualProtect не нужен сталобыть, PAGE_EXECUTE_READWRITE уже есть (0x40). код, кстати у меня работает