Есть одна игра в которой надо перехватить функцию WriteProcessMemory. Вообщем вопрос такого плана.Как это организовать на асме. А именно как получить правилный пид или хэндл kernel32.dll. Так как все мои попытки провалились решил спросить. Ногами просьа не пинать хотя этот вопрос подимался не раз во всех темах я для себя ответа не нашел
Это, наверно, можно и прорще сделать, но всё-же: Напиши код, внедри его в Game.exe так, что-бы он при запуске Game.exe первым получал управление. При старте Game.exe твой код должен изменить в IAT адрес соответствующий WriteProcessMemory на адрес твоего обработчика.
Для начала внедри dll таким способом: start proc invoke GetPidProcess,<АДРЕСС СТРОКИ С DLL> .if eax!=0 invoke CautchDll,eax,<имя dll из system32>,<размер> ret start endp CautchDll proc pPIDWORD,pDllNameWORD,szDllNameWORD ;;;;;;;;;; возвращает (eax=0-удача), (еах=-1)-ошибка LOCAL hprocWORD LOCAL pmemoryWORD LOCAL hthreadWORD invoke OpenProcess,PROCESS_ALL_ACCESS,0,pPID ;открываем процесс mov hproc,eax .if eax==0 or eax,-1 jmp CautchDllError ;;; ecли ошибка, то выходим .endif invoke VirtualAllocEx,eax,0,szDllName,MEM_COMMIT,PAGE_EXECUTE mov pmemory,eax invoke WriteProcessMemory,hproc,eax,pDllName,szDllName,0 ;;;переписываем имя DLL invoke GetModuleHandle,SADD("kernel32.dll") invoke GetProcAddress,eax,SADD("LoadLibraryA") invoke CreateRemoteThread,hproc,0,0,eax,pmemory,NULL,NULL mov hthread,eax .if eax==0 or eax,-1 ; если не получается создать поток, jmp CautchDllError ; то выходим invoke CloseHandle,hproc .endif invoke WaitForSingleObject,eax,-1 invoke CloseHandle,hthread invoke CloseHandle,hproc xor eax,eax CautchDllError: ret CautchDll endp .data ansi db 16 dup(0) .code .data ansi db 16 dup(0) .code GetPidProcess proc nprocWORD LOCAL PID[12]WORD LOCAL lengthbufWORD LOCAL bufWORD LOCAL leninfoWORD LOCAL numWORD mov num,0 mov ecx,12 mov eax,0 lea edi,PID rep stosd invoke NtQuerySystemInformation,5,0,0,addr lengthbuf ;получаем размер буфера invoke GlobalAlloc,GMEM_ZEROINIT,lengthbuf invoke GlobalLock,eax mov buf,eax ;buf -адресс буфера invoke NtQuerySystemInformation,5,buf,lengthbuf,addr leninfo mov esi,buf ;esi- адресс буфера с записанно информацией l1: mov ebx,[esi+NextEntryDelta] ; смещение на следующую элемент .if ebx==0 xor eax,eax jmp mend .endif mov eax,[esi+ProcessName] ;адресс unicode строки с именем invoke ConvertUnicode,eax,addr ansi;invoke lstrcmpW,eax, nproc invoke CharLower,addr ansi invoke lstrcmp,nproc,addr ansi .if eax!=0 nextid: add esi,ebx ;если строки не равны, то прибавим add esi,4 ;NextEntryDelta invoke IsBadHugeReadPtr,esi,4 .if eax==0 sub esi,4 jmp l1 .endif xor eax,eax jmp mend .endif ;если еах=0, то Id найден mov eax,[esi+ProcessId] mend: ret GetPidProcess endp ConvertUnicode proc uses esi edi ubufWORD,mansiWORD .if ubuf==0 jmp short ex .endif mov esi,ubuf mov edi,mansi cu1: .if word ptr [esi]!=0 mov ax,word ptr [esi] mov byte ptr [edi],al add esi,2 inc edi jmp short cu1 .endif mov byte ptr [edi],0 ex: ret ConvertUnicode endp
А в dllmain делаешь вот так: .data funcbytes db 7 dup(0) procaddr dd 0 .code NewFunctionBytes proc mov eax,offset hook_WriteProcessMemory call eax ret NewFunctionBytes endp iexploreProc proc param1WORD ;процедура, выполняющаяся, если мы в iexplore.exe invoke GetModuleHandle,SADD("kernel32.dll") invoke GetProcAddress,eax,SADD("WriteProcessMemory") mov procaddr,eax invoke VirtualProtect,procaddr,7,PAGE_EXECUTE_READWRITE,addr trID @copystr procaddr,offset funcbytes,7 ;и заменяем 7 байт @copystr offset NewFunctionBytes,procaddr,7 ;API фнкции ret iexploreProc endp .data resi dd 0 redi dd 0 recx dd 0 rebx dd 0 .code hook_WriteProcessMemory proc mov resi,esi mov redi,edi ;сохраняем регистры mov recx,ecx mov rebx,ebx @copystr offset funcbytes,procaddr,7 ;восстанавливаем байты push ebp mov ebp,esp param1 equ dword ptr [ebp+0Ch] param2 equ dword ptr [ebp+10h] param3 equ dword ptr [ebp+14h] param4 equ dword ptr [ebp+18h] param5 equ dword ptr [ebp+1ch] <Здесь делаешь то,что ты хочешь> leave pop ebx pop ebx ;восстанавливаем стек и вызываем call procaddr ;перехватываему фукнцию push ebx ;помещаем в стек обратный адресс @copystr offset NewFunctionBytes,procaddr,7 ;снова изменяем байты mov esi,resi mov edi,redi mov ecx,recx ;восстанавливаем регистры mov ebx,rebx ret hook_WriteProcessMemory endp
А в dllmain делаешь вот так: .data funcbytes db 7 dup(0) procaddr dd 0 .code NewFunctionBytes proc mov eax,offset hook_WriteProcessMemory call eax ret NewFunctionBytes endp iexploreProc proc param1WORD ;процедура, выполняющаяся, если мы в iexplore.exe invoke GetModuleHandle,SADD("kernel32.dll") invoke GetProcAddress,eax,SADD("WriteProcessMemory") mov procaddr,eax invoke VirtualProtect,procaddr,7,PAGE_EXECUTE_READWRITE,addr trID @copystr procaddr,offset funcbytes,7 ;и заменяем 7 байт @copystr offset NewFunctionBytes,procaddr,7 ;API фнкции ret iexploreProc endp .data resi dd 0 redi dd 0 recx dd 0 rebx dd 0 .code hook_WriteProcessMemory proc mov resi,esi mov redi,edi ;сохраняем регистры mov recx,ecx mov rebx,ebx @copystr offset funcbytes,procaddr,7 ;восстанавливаем байты push ebp mov ebp,esp param1 equ dword ptr [ebp+0Ch] param2 equ dword ptr [ebp+10h] param3 equ dword ptr [ebp+14h] param4 equ dword ptr [ebp+18h] param5 equ dword ptr [ebp+1ch] <Здесь делаешь то,что ты хочешь> leave pop ebx pop ebx ;восстанавливаем стек и вызываем call procaddr ;перехватываему фукнцию push ebx ;помещаем в стек обратный адресс @copystr offset NewFunctionBytes,procaddr,7 ;снова изменяем байты mov esi,resi mov edi,redi mov ecx,recx ;восстанавливаем регистры mov ebx,rebx ret hook_WriteProcessMemory endp
Извинюсь за повтор, коннект страшно тормозит. Ну подправь там маленько код и все будет работать, Если хочешь снизу dll, можешь скачать, которая импортирует CautchDll и GetPidProcess (имя процесса в UNICODE передавай) CautchDll PROTO WORD,WORD,WORD ;внедряет dll в процесс ;1-PID процесса ;2-указатель на имя dll ;3-размер имени dll GetPidProcess PROTOWORD ;получение PID процесса по имени ;1-указатель на имя процесса (UNICODE) _1358421148__Cautch&Pid.dll
И не забудь подправить в функции GetPidProcess: MAX_PROCESS_NAME_LENGTH equ <сколько надо> ansi db MAX_PROCESS_NAME_LENGTH dup(0) LOCAL PID[MAX_PROCESS_NAME_LENGTH]:WORD
Провозившись долго я так и не смог понять как объявит структуры SYSTEM_PROCESSES если не сложно то объясните как ее объявитьт чтобы можно использовать ProcessId,ProcessName,NextEntryDelta
Код (Text): CLIENT_ID STRUCT UniqueProcess dd ? UniqueThread dd ? CLIENT_ID ENDS SYSTEM_THREADS struct KernelTime LARGE_INTEGER <> UserTime LARGE_INTEGER <> CreateTime LARGE_INTEGER <> WaitTime dd ? StartAddress dd ? ClientId CLIENT_ID <> Priority SDWORD ? BasePriority SDWORD ? ContextSwitchCount dd ? State dd ? WaitReason dd ? SYSTEM_THREADS ends VM_COUNTERS STRUCT PeakVirtualSize DWORD ? VirtualSize DWORD ? PageFaultCount DWORD ? PeakWorkingSetSize DWORD ? WorkingSetSize DWORD ? QuotaPeakPagedPoolUsage DWORD ? QuotaPagedPoolUsage DWORD ? QuotaPeakNonPagedPoolUsage DWORD ? QuotaNonPagedPoolUsage DWORD ? PagefileUsage DWORD ? PeakPagefileUsage DWORD ? VM_COUNTERS ENDS SYSTEM_PROCESSES struct NextEntryDelta dd ? ThreadCount dd ? Reserved1 dd 6 dup (?) CreateTime LARGE_INTEGER <> UserTime LARGE_INTEGER <> KernelTime LARGE_INTEGER <> ProcessName UNICODE_STRING <> BasePriority SDWORD ? ProcessId dd ? InheritedFromProcessId dd ? HandleCount dd ? Reserved2 dd 2 dup (?) VmCounters VM_COUNTERS <> ;IO_COUNTERS IoCounters; // Windows 2000 only Threads SYSTEM_THREADS <> SYSTEM_PROCESSES ends
Серавно одни каракулы. Код (Text): local cb:dword invoke NtQuerySystemInformation,5,0,0,addr cb invoke GlobalAlloc,0h or 40h,cb mov esi,eax assume esi:ptr SYSTEM_PROCESSES invoke NtQuerySystemInformation,5,esi,cb,0 test eax,eax jnz _exit @@: invoke MessageBoxW,0,addr [esi].ProcessName,addr [esi].ProcessName,0 mov ebx,[esi].NextEntryDelta add esi,ebx cmp ebx,0 jnz @B assume esi:nothing _exit:ret
Странно.. И раньще пробовал юзать RtlUnicodeStringToAnsiString, серавно каракулы показывало. А щас поставил, и на те, работает cresta, опять колдавством балуешся ? )