Добрый день, форумчане. В данный момент прохожусь по данному мануалу. Переписываю код под fasm со своими модификациями(костылями) ,в общем учусь, практикуюсь и все такое. Там есть сэмпл, который немного смутил меня. Код (ASM): ;######################################################################### ;Процедура GetBase ;Поиск базы исполняемого файла, если есть адрес где-то внутри него ;Вход: В esi - адрес внутри файла в памяти ;Выход:В eax - база PE-файла ;Заметки:обычно процедура используется с спроецируемыми файлами в память ;######################################################################### GetBase proc LOCAL Base:DWORD;чтобы не изменять контекст по договоренности push esi;сохраняем все регистры, которые используются push ecx pushf;сохраняем регистр флагов and esi,0FFFF0000H;гранулярность выделения памяти mov ecx,6;счетчик страниц NextPage:;проверка очередной страницы call ValidPE .IF eax==1 mov Base,esi popf pop ecx pop esi mov eax,Base ret .ENDIF sub esi,10000H loop NextPage popf;восстанавливаем значения флагов pop ecx pop esi;восстанавливаем значения регистров mov eax,FALSE;не нашли базу :( ret GetBase endp ;######################################################################### ;Конец процедуры GetBase ;######################################################################### А именно, вот этот участок: Код (ASM): mov Base,esi popf pop ecx pop esi mov eax,Base ret Зачем мы сохраняем адрес из esi в локальную Base,а потом из Base в eax, если можно просто mov eax, esi pop esi ?
Спасибо. Я себя в ассме пока неуверенно чувствую, поэтому и не чую подвоха особо, но этот случай особенно в глаза бросился.
Всегда пожалуйста. Способов найти базу Kernel32, наверное, полдюжины. Но на Висте+, таким образом, если не ошибаюсь, находится KernelBase.dll.
_edge, да, для win7+ придется иначе реализовывать. Я пока только тренируюсь, дальше уже буду подтачивать в процессе создания своего.
С конкретными алго можно пока не торопиться, это никуда не убежит. Имхо лучше пока базу обкатывать, вроде извращений с регистрами и циклов, чтобы их "влет" понимать, вне зависимости от их "махровости". Т.е. пока отойти от викс-не викс, и рассматривать асм все ОС. Чтобы не было затыков на конструкциях вроде этой, когда думаешь "что он здесь удумал делать?" ) "вредные советы" Евгения Остера http://z0mbie.daemonlab.org/21zero.html А также команды TEST, OR, AND для работы с частями байтов. Конечно у 386+ есть bit-test/bit-set команды, но часто именно встречаешь какой-нибудь AND.
_edge, эти мнемоники я знаю, даже почти сразу понял, что сделал автор и почему именно ffff0000 Код (ASM): and esi,0FFFF0000H; Страничка Зомби открыта во вкладках, но пока хочу окончательно с PE разобраться и методами его инфицирования. Это вполне себе практические задачи, которые интересно решать и одновременно учиться. Если есть инфа по win7 ,то поделитесь, пожалуйста источниками) А то пока нашел только сорцы, где автор не особо густо объясняет принцип. Еще на rohitab немного нашел.
Xм, по мне - так пахнет "компилятором"… Хотя, мои познания давным давно устарели… В свою очередь, от себя я бы этот код писал бы так Код (ASM): popf pop ecx xchg esi,[esp] pop eax ret P.S.: Выглядит странно… Но, этим бы выделилось, что Код писался человеком Код писался мною
Код (ASM): xchg esi,[esp] Очень медленная инструкция. Словил лулзов, когда производительность моей реализации FFT из-за этой инструкции упала раз в десять. А разгадка проста - на время выполнения блокируется шина данных.
SadKo, Профайл: xchg eax,[esp] / xchg [esp],eax - идентичный. mov ecx,[esp] mov [esp],eax mov eax,ecx В 3 раза быстрее xchg. Но никак не в 10.
Вoт вот, проблема в том, что такая безобитная инструкция фокусничает с шиной. Но, выход давно найден в Microsoft. P.S.: Кто не понял, о чём я… Раньше каждый лишний вывод микросхемы имел свою стоимость (читал как-то про отличия сложности производства корпусов на 14, 16 и т.д. ног) и всё мультиплексироварось в "узких местах" (RAS/CAS в DRAM, A0/D0..A7/D7 у i8088 и т.д.). Но, у динамического ОЗУ была особенность - данные на запись и читаемые данные имели отдельные выводы. Тем самым, если бы у процессоров для доступа к памяти существовали шина читаемых и шина записываемых данных, блокировать шину бы не пришлось: xchg esi,[esp] одновременно и читала бы слово, и писало бы по разным шинам
SadKo, Копался в ядре, попалась интересная конструкция. Два обмена в памяти сделаны для задержки, ожидание переключения контекста.
Indy_, а способ достать базу kernel32.dll с получением ret адреса из стека в самом начале тела вируса, который указывает куда-то в середину kernel32.dll с дальнейшим пролистыванием по 64kb назад пока не наткнемся на сигнатуру PE\0\0 еще работает? Потому что результат такой же как при использовании другого способа: Код (ASM): mov ebx, [FS : 0x30] ; get a pointer to the PEB mov ebx, [ebx + 0x0C] ; get PEB->Ldr mov ebx, [ebx + 0x14] ; get PEB->Ldr.InMemoryOrderModuleList.Flink (1st entry) mov ebx, [ebx] ; 2nd Entry mov ebx, [ebx] ; 3rd Entry mov ebx, [ebx + 0x10] ; Get Kernel32 Base
psh3nka, Не, такое не годится. Во первых нельзя абы откуда обратиться абы куда - NX. В частности NX-SEH(это не просто резолвится). Во вторых считается что простое разыменование списка не есть гуд. Нужно пройти по связанному списку загрузчика и вычислить(взять") хэш от имени модуля. Код (Text): ; + ; assume fs:nothing LdrGetNativeBase proc uses ebx esi edi mov ebx,fs:[TEB.Peb] mov ebx,PEB.Ldr[ebx] lea ebx,PEB_LDR_DATA.InMemoryOrderModuleList[ebx] ; Head assume ebx:PLIST_ENTRY mov esi,[ebx].Flink assume esi:PLIST_ENTRY .while Ebx != Esi lea edi,[esi][-LDR_DATA_TABLE_ENTRY.InMemoryOrderModuleList] assume edi:PLDR_DATA_TABLE_ENTRY movzx eax,[edi].BaseDllName._Length invoke LdrCalcHash, [Edi].BaseDllName.Buffer, Eax .if Eax == 0A5951FEH mov eax,[edi].DllBase jmp Exit .endif mov esi,[esi].Flink .endw xor eax,eax Exit: test eax,eax ret LdrGetNativeBase endp Табуляция конечно офигенна, как собственно и само наличие тега кода
Вот эту строчку не совсем понял А предыдущие два примера что в себе содержат? У меня просто подозрение, что там kernelbase, а не kernel32
psh3nka, > А предыдущие два примера что в себе содержат? Да какая разница, хэш нужный забейте туда. И вообще, это для обучения только, что бы вы вкурили что такое двусвязные списки. Вроде как я только один привёл. Впрочем и так всё ясно)
У меня схожий вопрос. Делаем exe, состоящий из одной инструкции ret. Грузим в Ольку, шагаем into, Чем не Кернел32? Это я запускал 32-бит exe на вин7-64. -- По двусвязным спискам находится здесь такое http://wasm.in/forum/threads/kak-poluchit-komandnuju-stroku-storonnego-processa.24418/ Двусвязный список - это структура данных, которая состоит из узлов, которые хранят полезные данные, указатели на предыдущий узел и следующий узел. /Гугл/ -- Ожидая возможные грабли с Фасмом и FS:, напишу как его адресовать, fs mov eax,[something]
Код (ASM): assume fs:nothing LdrGetNativeBase proc uses ebx esi edi mov ebx,fs:[TEB.Peb] mov ebx,PEB.Ldr[ebx] lea ebx,PEB_LDR_DATA.InMemoryOrderModuleList[ebx] ; Head assume ebx:PLIST_ENTRY mov esi,[ebx].Flink assume esi:PLIST_ENTRY .while Ebx != Esi lea edi,[esi][-LDR_DATA_TABLE_ENTRY.InMemoryOrderModuleList] assume edi:PLDR_DATA_TABLE_ENTRY movzx eax,[edi].BaseDllName._Length invoke LdrCalcHash, [Edi].BaseDllName.Buffer, Eax .if Eax == 0A5951FEH mov eax,[edi].DllBase jmp Exit .endif mov esi,[esi].Flink .endw xor eax,eax Exit: test eax,eax ret LdrGetNativeBase endp
Paguo_86PK, Спасибо, это уже норм читабельно. Как вы это запостили ? _edge, > Чем не Кернел32? Это я запускал 32-бит exe на вин7-64. Анстаб метод. Тем более обычно не имеется стартап контекста. > Двусвязный список - это структура Спасибо я вкурсе. Мне уже эти списки весь мозг проели.)