примерно так: Код (Text): BOOL InjectIntoProcess(HANDLE p_handle, PVOID proc) { PBYTE Buffer; DWORD dwRead=0; DWORD dwSize = ((PIMAGE_OPTIONAL_HEADER)((LPVOID)((BYTE *)(BASEADDR) + ((PIMAGE_DOS_HEADER)(BASEADDR))->e_lfanew + sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER))))->SizeOfImage; Buffer = (PBYTE)VirtualAlloc(NULL, dwSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); if (Buffer == NULL) return FALSE; ReadProcessMemory(GetCurrentProcess(), (LPCVOID)BASEADDR, (LPVOID)Buffer, dwSize, &dwRead); PBYTE pMem = (PBYTE)VirtualAllocEx(p_handle, (LPVOID)BASEADDR, dwRead, MEM_COMMIT|MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (Buffer == NULL) return FALSE; DWORD dwOldProt, dwNumBytes; VirtualProtectEx(p_handle, pMem , dwRead, PAGE_EXECUTE_READWRITE, &dwOldProt); if (!WriteProcessMemory(p_handle, pMem, Buffer, dwRead, &dwNumBytes)) return FALSE; DWORD dwThreadId; CreateRemoteThread(p_handle, NULL, 0, proc, NULL, 0, &dwThreadId); return TRUE; } /* p_handle - хендл процесса в который нужно инжектнуццо proc - аддресс ф-ции, которая будет выполняться в удалённом потоке BASEADDR - ImageBase бинарника, который делает инжект */
делюсь 32-64 битный инжект-ремув показывает код ошибки LoadLibrary можно задавать PID можно имя процесса
>> Cr4sh а шо если BASEADDR занят? выбирай такой, чтоб он не оказался занятым, а что, есть другие идеи? =) хотя можно писать базонезависимый код, и инжектить его куда попало... >> затрецо чужой исполняемый код ничего не затётся, просто VirtualAllocEx не сработает
>> выбирай такой, чтоб он не оказался занятым таких адресов НЕТ >> ничего не затётся, просто VirtualAllocEx не сработает VirtualAllocEx cannot reserve a reserved page. It can commit a page that is already committed. This means you can commit a range of pages, regardless of whether they have already been committed, and the function will not fail. >> есть другие идеи? =) >> хотя можно писать базонезависимый код, и инжектить его куда попало... идея читать ртфм Код (Text): #include <windows.h> #include <Dbghelp.h> bool inject_pe(DWORD pid, void * pe) { HANDLE host = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if ( ! host ) return false; char * img = reinterpret_cast<char*>(pe); const IMAGE_DOS_HEADER & dh = *reinterpret_cast<IMAGE_DOS_HEADER*>(img); IMAGE_NT_HEADERS & nth = *reinterpret_cast<IMAGE_NT_HEADERS*>(img + dh.e_lfanew); const IMAGE_FILE_HEADER & fh = nth.FileHeader; const IMAGE_OPTIONAL_HEADER & oh = nth.OptionalHeader; const ULONG image_size = oh.SizeOfImage; char * base = reinterpret_cast<char*>(VirtualAllocEx(host, 0, image_size, MEM_COMMIT, PAGE_READWRITE)); if ( ! base ) goto panic; const IMAGE_SECTION_HEADER * section = reinterpret_cast<IMAGE_SECTION_HEADER*> (reinterpret_cast<UINT_PTR>(&oh) + fh.SizeOfOptionalHeader); // imports // note: we exploit the fact, that system dll are mapped to // the same addresses in all process spaces // (however, injected code has to load these dlls itself) const IMAGE_DATA_DIRECTORY & imp_dir = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; const IMAGE_IMPORT_DESCRIPTOR * idesc = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*> (ImageRvaToVa(&nth, img, imp_dir.VirtualAddress, NULL)); for ( ; idesc->Characteristics; ++idesc ) { HMODULE dll = LoadLibraryA((char*)ImageRvaToVa(&nth, img, idesc->Name, NULL)); if ( ! dll ) goto panic; IMAGE_THUNK_DATA * import = reinterpret_cast<IMAGE_THUNK_DATA*> (ImageRvaToVa(&nth, img, idesc->OriginalFirstThunk, NULL)); IMAGE_THUNK_DATA * thunk = reinterpret_cast<IMAGE_THUNK_DATA*> (ImageRvaToVa(&nth, img, idesc->FirstThunk, NULL)); for ( ; import->u1.Function; ++import, ++thunk ) { DWORD ordanal = import->u1.Ordinal; FARPROC proc = 0; if ( 0x80000000 & ordanal ) proc = GetProcAddress(dll, MAKEINTRESOURCE(ordanal)); else { const IMAGE_IMPORT_BY_NAME * pimp_name = reinterpret_cast<IMAGE_IMPORT_BY_NAME*> (ImageRvaToVa(&nth, img, ordanal, NULL)); proc = GetProcAddress(dll, reinterpret_cast<const char*>(pimp_name->Name)); } if ( !proc ) { FreeLibrary(dll); goto panic; } thunk->u1.Function = reinterpret_cast<DWORD>(proc); } FreeLibrary(dll); } // fixups struct IMAGE_BASE_RELOCATION { DWORD VirtualAddress, SizeOfBlock; struct Item { WORD Offset:12; WORD Type:4; } item[1]; }; unsigned const fix_va = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; if ( ! fix_va ) goto panic; unsigned const fix_size = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; const IMAGE_BASE_RELOCATION * fixups = reinterpret_cast<IMAGE_BASE_RELOCATION*> (ImageRvaToVa(&nth, img, fix_va, NULL)); const UINT_PTR end = (UINT_PTR)ImageRvaToVa(&nth, img, fix_va + fix_size, NULL); const size_t delta = reinterpret_cast<UINT_PTR>(base) - oh.ImageBase; while ( reinterpret_cast<UINT_PTR>(fixups) < end ) { char * const addr = (char*)ImageRvaToVa(&nth, img, fixups->VirtualAddress, NULL); UINT_PTR end = fixups->SizeOfBlock + reinterpret_cast<UINT_PTR>(fixups); const IMAGE_BASE_RELOCATION::Item * i = &fixups->item[0]; for ( ; reinterpret_cast<UINT_PTR>(i) < end; ++i ) if ( i->Type == IMAGE_REL_BASED_HIGHLOW ) *reinterpret_cast<DWORD*>(&addr[i->Offset]) += delta; fixups = reinterpret_cast<const IMAGE_BASE_RELOCATION*>(i); } // inject sections for ( int i = 0; i != fh.NumberOfSections; ++i ) { const ULONG virtual_size = section[i].Misc.VirtualSize; const ULONG raw_size = section[i].SizeOfRawData; const SIZE_T size = raw_size < virtual_size ? raw_size : virtual_size; SIZE_T written = 0; WriteProcessMemory(host, base + section[i].VirtualAddress, img + section[i].PointerToRawData, size, &written); if ( written != size ) goto panic; const ULONG c = section[i].Characteristics; DWORD protect = PAGE_READONLY; if ( c & IMAGE_SCN_MEM_WRITE ) protect = PAGE_READWRITE; if ( c & IMAGE_SCN_MEM_EXECUTE ) protect = PAGE_EXECUTE_READ; if ( c & IMAGE_SCN_MEM_EXECUTE && c & IMAGE_SCN_MEM_WRITE ) protect = PAGE_EXECUTE_READWRITE; DWORD old_protect; VirtualProtectEx(host, base + section[i].VirtualAddress, virtual_size, protect, &old_protect); } // start HANDLE thread = CreateRemoteThread(host, NULL, 0, (LPTHREAD_START_ROUTINE)(base + oh.AddressOfEntryPoint), NULL, 0, NULL); if ( thread ) { CloseHandle(thread); CloseHandle(host); return true; } panic: CloseHandle(host); return false; }
Блин может не совсем в тему но новый топ открывать не охота на делфях или на асме инжект может кто скинет.
>> таких адресов НЕТ дада, все два гига юзермодного адрессного пространства забиты под чистую)) >> идея читать ртфм а если бинарник будет без фиксапов?) хотя хз, с другой стороны никто не мешает скомпилить его чтоб он был...
Инжект через CreateRemoteThread. На делфе. Код (Text): function InjectViaCreateRemoteThread(ProcessID:Cardinal; DllPath:String):Boolean; var pDllName:pointer; hProcess,hThread:Thandle; BytesWritten,TheadID:Cardinal; begin result:=false; hProcess:=OpenProcess(PROCESS_ALL_ACCESS,False,ProcessID); if (hProcess=0) then exit; pDllName:=VirtualAllocEx(hProcess,Nil,Length(DllPath),MEM_COMMIT,PAGE_READWRITE); if (pDllName <> nil)and(WriteProcessMemory(hProcess,pDllName,PChar(DllPath),Length(DllPath),BytesWritten)) then begin hThread:=CreateRemoteThread(hProcess,nil,0,GetProcAddress(LoadLibrary('kernel32.dll'),'LoadLibraryA'),pDllName,0,TheadID); if hThread<>0 then begin result:=true; WaitForSingleObject(hThread,INFINITE); VirtualFreeEx(hProcess,pDllName,0,MEM_RELEASE); end; end; CloseHandle(hProcess); end;
А полностью рабочий с Dll'ой. Просто все кричат что в статьях "Перехват API функций в Windows NT" все гуд описано ну так приатачили бы к ним пример инжекта dll и половина вопросов бы спразу отпала. Самому учиться хорошо но временами лучше идти по уже протоптанной дороге.
>> дада, все два гига юзермодного адрессного пространства забиты под чистую)) достаточно что б несколько кб были заняты... нужные... ты ж видиш ща модно несильно задумываясь копипастить чужие сорцы... и ктото откопипастит твой базовый адрес =) >> а если бинарник будет без фиксапов?) >> хотя хз, с другой стороны никто не мешает скомпилить его чтоб он был... если есть сорцы то нет трабл создать фиксапы... плюсов это даст чуток... на первый взгляд + к размеру но реально позиционно независимый код на асме получаеццо больше =) >> Самому учиться хорошо но временами лучше идти по уже протоптанной дороге и придеш туда где все места заняты :P для современных фаеров весь код веше неактуален =)
>> А вот с этим можно поспорить. я ничо никому доказывать не хочу а если действительна хошь спорить делой ставки и подумоем >> а есть актуальный пример ? =) есть =) тока после публикации он станет неактуальный .