Доброго времени суток! предистория такова: есть одна статическая длл-ка, а в ней в нужный момент выполнения кода мне нужно подменить значение регистра.регистр содержит координату, далее записывает ее в стек и отправляет в видеопамять. я собираюсь перед отправкой в видео память подставить свою координату и отправить ее в видео память. соотвествеено ето я планирую сделать путем передачи управления процедуре в собственно написанной длл-ке, которая рассчитает требуемую координату, далее вернет управление оригинальному коду и тот уже запишет в видеопамять нужную координату.место внедрения найдено,место для оператора call есть(за счет арифметических действий, которые уже не нужны, т.к. координата вычисляется в моей длл).поетому внедрение имеет смысл делать с затиранием ориг кода и вставлением туда операнда call. иными словами, мне нужно сделать внедрение с затиранием, чтобы передать управление своей длл-ке, которая заменяет значение регистра,и далее возвращает управление оригинальному коду. Задача весьма тривиальная, и по ней есть много литературы.Изучив соотвествующую литературу (Крис Касперски, статьи и туториалы по РЕ файлам и изменение в них и т.п. в т.ч. и с етого сайта) я нашел общую последовательность выполнения данной операции: необходимо написать патчер, который: 1) отредактирует таблицу импорта оригинальной длл 2) собственно подставит в нужное место оператор call 3) ну собсна вот и все никаких защит и скрывнаия следов редактирования н етребуется. я канеш понимаю, что задача тривиальная...но вот.... с теоритической частью все более менее понятно. а вот с практической-не совсем =/ сделать ето правильно(хотябы даже пока без патчера, а чисто ручками при помощи хекс редакторов не удается) впрочем, воспользовавшись поиском нашел темы, где товарищи писали что такой код можно наваять на плюсах чуть ли не за полчаса. но почему то никто исходничков так и не приложил... или я плохо искал.=/ собственно я и прошу поетому помочь с практической частью: может есть у кого какие нибудь исходнички подобных патчеров для образца? правильно ли я понимаю, что исходя из структуры РЕ файла после таблицы импорта будет место забитое нулями для выравнивания размера секции? поделитесь плз практическим опытом кто как добавлял в длл вызов сторонней длл или ткните плз носом на статьи конкретно по теме написания подобных патчеров с примерами. Заранее спасибо! ЗЫ: если тема не в той ветке создана, прошу перенести в нужную ветку.
Если не хочется/не получается прописать руками, то для добавления своей dll в таблицу импорта рекомендую Stud PE: http://www.google.com/search?q=Stud+PE&ie=UTF-8
большое спасибо! попробую обязательно ибо перед написание патчера мне нужно сделать хотябы как нибудь чтобы работало для того чтобы рзаобраться в процессе
я делал так. расширял последнюю секцию на нужный размер с учетом выравнивания (IMAGE_OPTIONAL_HEADER.FileAlignment), переносил туда исправленную таблицу импорта... короче сорец вот, расписывать лень. Код (Text): RVAToOffset proc uses ebx hview:dword,rva:dword mov ebx,hview add ebx,(IMAGE_DOS_HEADER ptr [ebx]).e_lfanew add ebx,sizeof dword mov cx,(IMAGE_FILE_HEADER ptr [ebx]).NumberOfSections movzx ecx,cx add ebx,sizeof IMAGE_FILE_HEADER + sizeof IMAGE_OPTIONAL_HEADER mov edx,rva @@: cmp edx,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress jl @next_sec mov eax,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress add eax,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData cmp edx,eax jl @f @next_sec: add ebx,sizeof IMAGE_SECTION_HEADER loop @b xor eax,eax ret @@: mov eax,rva sub eax,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress add eax,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add eax,hview ret RVAToOffset endp AddImport proc szTarget:dword local strbuf:dword local hfile:dword local hmap:dword local hview:dword local tdw:dword local ImportDir:dword local OrigImportOffs:dword local OrigImportSize:dword local SectionAlignment:dword local cblsRaw:dword local cblsVSize:dword local CheckSum:dword mov strbuf,func(HeapAlloc,pheap,HEAP_ZERO_MEMORY,100h) invoke wsprintf,strbuf,chr$("%s.new_import"),szTarget invoke CopyFile,szTarget,strbuf,FALSE xor eax,eax mov hfile,func(CreateFile,strbuf,GENERIC_ALL,eax,eax,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,eax) cmp eax,INVALID_HANDLE_VALUE jz @error xor eax,eax mov hmap,func(CreateFileMapping,hfile,eax,PAGE_READWRITE,eax,eax,eax) test eax,eax jz @error xor eax,eax mov hview,func(MapViewOfFile,hmap,FILE_MAP_READ or FILE_MAP_WRITE,eax,eax,eax) test eax,eax jz @error ;получаем смещение и размер импорта mov ebx,hview add ebx,(IMAGE_DOS_HEADER ptr [ebx]).e_lfanew add ebx,sizeof IMAGE_FILE_HEADER + sizeof dword lea ebx,(IMAGE_OPTIONAL_HEADER ptr [ebx]).DataDirectory ;считаем смещение import table add ebx,sizeof IMAGE_DATA_DIRECTORY*1 ;Import mov ImportDir,ebx m2m OrigImportSize,dword ptr [ebx+4] mov eax,[ebx] test eax,eax jz @error mov OrigImportOffs,func(RVAToOffset,hview,eax) ;go to last section mov ebx,hview add ebx,(IMAGE_DOS_HEADER ptr [ebx]).e_lfanew add ebx,sizeof dword mov eax,sizeof IMAGE_SECTION_HEADER mul (IMAGE_FILE_HEADER ptr [ebx]).NumberOfSections sub eax,sizeof IMAGE_SECTION_HEADER push eax add ebx,sizeof IMAGE_FILE_HEADER ;calc last section addition size's mov ecx,OrigImportSize add ecx,sizeof IMAGE_IMPORT_DESCRIPTOR + sizeof dword + sizeof dword + 20h mov eax,(IMAGE_OPTIONAL_HEADER ptr [ebx]).FileAlignment @@: cmp ecx,eax jle @f add eax,(IMAGE_OPTIONAL_HEADER ptr [ebx]).FileAlignment jmp @b @@: mov cblsRaw,eax mov ecx,(IMAGE_OPTIONAL_HEADER ptr [ebx]).SectionAlignment @@: cmp ecx,eax jle @f add eax,(IMAGE_OPTIONAL_HEADER ptr [ebx]).FileAlignment jmp @b @@: mov cblsVSize,eax add ebx,sizeof IMAGE_OPTIONAL_HEADER pop eax add ebx,eax mov strbuf,func(HeapReAlloc,pheap,0,strbuf,cblsRaw) mov ecx,cblsRaw xor eax,eax mov edi,strbuf rep stosb mov ecx,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add ecx,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData invoke SetFilePointer,hfile,ecx,0,FILE_BEGIN invoke WriteFile,hfile,strbuf,cblsRaw,addr tdw,0 mov edi,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add edi,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData add edi,sizeof IMAGE_IMPORT_DESCRIPTOR add edi,hview mov esi,OrigImportOffs mov ecx,OrigImportSize rep movsb mov edi,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add edi,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData add edi,hview add edi,cblsRaw sub edi,20h invoke lstrcat,edi,chr$("your.dll") sub edi,8 mov dword ptr [edi],80000001h mov eax,edi mov edi,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add edi,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData add edi,hview sub eax,hview sub eax,(IMAGE_SECTION_HEADER ptr [ebx]).PointerToRawData add eax,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress stosd ;Import LookUp xor eax,eax stosd ;Time/Date Stamp stosd ;Forward Chain mov eax,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress add eax,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData add eax,cblsRaw sub eax,20h stosd ;Name RVA mov eax,OrigImportOffs mov eax,dword ptr [eax+10h] stosd ;Addres Table RVA mov edi,ImportDir mov eax,(IMAGE_SECTION_HEADER ptr [ebx]).VirtualAddress add eax,(IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData stosd ;rva таблицы mov eax,OrigImportSize add eax,sizeof IMAGE_IMPORT_DESCRIPTOR stosd ;размер таблицы ;правим заголовок последней секции ;SizeOfRawData mov eax,cblsRaw add (IMAGE_SECTION_HEADER ptr [ebx]).SizeOfRawData,eax ;VirtualSize mov eax,cblsVSize add (IMAGE_SECTION_HEADER ptr [ebx]).Misc.VirtualSize,eax ;Characteristics mov (IMAGE_SECTION_HEADER ptr [ebx]).Characteristics,IMAGE_SCN_MEM_READ or IMAGE_SCN_MEM_WRITE or IMAGE_SCN_CNT_INITIALIZED_DATA add edi,18 *sizeof dword ;Bound Import xor eax,eax stosd stosd ;IMAGE_OPTIONAL_HEADER.SizeOfImage mov ebx,hview add ebx,(IMAGE_DOS_HEADER ptr [ebx]).e_lfanew add ebx,sizeof IMAGE_FILE_HEADER + sizeof dword mov eax,(IMAGE_OPTIONAL_HEADER ptr [ebx]).SizeOfImage add eax,cblsVSize mov (IMAGE_OPTIONAL_HEADER ptr [ebx]).SizeOfImage,eax mov CheckSum,func(GetFileSize,hfile,0) invoke LoadLibrary,chr$("imagehlp.dll") test eax,eax jz @f invoke GetProcAddress,eax,chr$("CheckSumMappedFile") test eax,eax jz @f mov edx,eax invoke f4 ptr edx,hview,CheckSum,addr tdw,addr CheckSum mov eax,CheckSum mov (IMAGE_OPTIONAL_HEADER ptr [ebx]).CheckSum,eax @@: invoke UnmapViewOfFile,hview invoke CloseHandle,hmap invoke CloseHandle,hfile invoke HeapFree,pheap,0,strbuf mov eax,TRUE ret @error: xor eax,eax ret AddImport endp
detours от microsoft research, вроде умеет добавлять, если нужен код на СИ http://research.microsoft.com/en-us/projects/detours/
спасибо всем за помощь! за примеры исходников отдельное большое спасибо! помогло, с таблицей импорта удачно разобрался. ---- чтобы не создавать отдельную тему: сейчас остался один мелкий штришок в плане работы загрузчика. как известно-при загрузке длл загрузчик перебазирует длл в память. чаще всего-он ето делает в одно и то же место(в некое оптимальное смещение). используя таблицы экспорта/импорта и т.п. ессна при перебазировании он соотвествующим образом меняет код, чтобы ссылки указывали в нужное место. ессна можно прогрузиться под отладчиком, посмотреть куда он перебазирует и вычислить адрес и жестко забить его в код. программа будет рбаотать. но ето индийский способ-ибо перебазируй он по др смещению-и все, прога работать небудет. по хорошему, нужно сделать так чтобы загрузчик все же сам пересчитывал в зависимости от того, куда он грузит длл. собственно вот этот момент пока сделать не удается: вроде все делаю по образцу, но при загрузке загрузчик оставляет нужную строчку неизменной. т.е., как было. к примеру:загрузка перебазирует длл в 00001000. но мой оператор jmp ds:10101010(оп. код ff 25 10 10 10 10) при загрузке не изменяется, хотя по идее он должен загрузиться как jmp ds:10102010. поиски по мануалам и статьям о загрузчике пока эффекта не дали( может кто подскажет, по какому критерию загрузчик определяет какие адреса нада модифицировать при загрзке, а какие нет? ну или плз кинте ссылочкой на толковую статью(книгу) по работе загрзчика, где ето можно прочитать гуглом искал, чес слово. заранее спасибо!
Нифига не понятно что тебе надо. Ты про загрузку длл, в который ты хукаешь, в другое место? Если да то надо определять адрес ф-ции динамически, забивать жестко смещения это зло. В крайнем случае забивай RVA и потом корректируй на базу длл-ки. Твой жестко вбитый адрес никакой загрузчик не исправит. Есть релоки, но они для адресов внутри твоего модуля а не для внешних. Еще есть дельта смещение. Гугли
не надо никаких джампов вписывать в код, твоего джампа не будет в релоках и загрузчик его пропустит. забей на это. загрузчик в любом случае выполнит точку входа в твою длл, отсюда и пляши. но не забывай, есть ограничения на то чего можно делать в точке входа, а чего нет.
к сожалению у меня еще есть проблемы со знанием терминов(т.е. изъясняюсь на пальцах) и,похоже, с пониманием процесса работы загрузчика... да, вот именно что зло. но как сделать по доброму-над етим я сейчас как раз и работаю с наскоку взять ессна не получилось, поетому сейчас потихоньку изучаю теорию но она часто на английском, а ето еще больше вносит путаницу для меня в терминах( правильно ли я понимаю, что речь идет о корректировании точки rebasing while loading? т.е. смещения в памяти, начиная с которого прогружается и располагается в памяти машинный код длл-ки? ага) и ессна не исправляет он) и ето меня печалит) спасибо, попробую погуглить по ключевым словам нада сказать, что самая большая проблема в гуглении-ето как раз незнание мной терминов. ибо получается ищу то-сам не знаю что... но многих нужных вещей на русском нагуглить в итоге не удаеться,и в итоге еще большую путаницу вносит лит-ра на английском гм...а во всех найденных мной в гугле источниках и примерах все ето сводиться к примерно такому алгоритму: 1) вычищаем свободное место(или делаем его путем добавления новой секции и т.д.) 2) в ето место пишем код, суть которого сводиться к джампу на точку входа как на жесткий адрес(вот такой джамп нам нужен: FF 25 ХХ ХХ ХХ ХХ ХХ Jump to call gate, same privilege) 3) в месте, где мы хотим врезаться, пишем относительный ближний call(relative near call),который ведет нас на джамп, который уже и передает управление др. длл... вот такой алгоритм я и реализовал...оно даже работает, но на жесткой адресации собственно тут я понял, что либо я чта не так понял в примерах, либо они чета не написали...начал копать...и копаю вот потихоньку по гуглу сейчас даже нашел пример исходника для простейшего виндоусовского загрузчика на плюсах спасибо всем откликнувшимся! с вашей помощь и помощью гугла я думаю все получиться
хз, в который раз читаю что не могут найти документацию. Я в свое время прочитал какую-то доку по PE-формату на русском, и пару статей на васме, типа "об упаковщиках в последний раз", "от зеленого к красному" и т .д. Залазишь во все разделы и смотришь статьи и примеры.
в моем случае вся проблема была в том, что я не знал точной терминологии, а общий смысл как раз представлял. в статьях то зачастую авторы допускают жаргонизмы, посему у меня и возникла путаница:гугл выдавал что то невнятное. Благодаря Вашим ключевым словам, что были указаны в постах выше общение с гуглом пошло намного живее и я нашел примерно следующее. утилита для редактирования релоков(релокаций,таблицы релокаций и т.п.) существует и называется Bin_RelocEditor_2008-7-23_21.12_RelocEdit (гугл ее находит легко на слово RelocEdit) например вот ссылочка: http://www.woodmann.com/collaborative/tools/index.php/RelocEditor гораздо интереснее обстоят дела с инструкцией к ней. она нашлась на одном форуме, где у меня антивирус ругался благим матом, посему сюда ее просто перепощу: вот собственно и все. дальше все банально ------------------------------------------------ ЗЫ:алгоритм работает, все вроде хорошо. временин е было вс еотписаться,а ща вот решил таки запостить пост, ибо мало ли кому поможет при редактировании релоков. всем спасибо за помощь! тему имхо можно закрывать.