Как извлечь шеллкод из памяти
Форензика
1,812
Вредоносные программы иногда запускают шеллкод прямо в памяти. В этой небольшой статье я покажу, как извлечь шеллкод из памяти.
Еще по теме: Как обнаружить шелл-кoд на взломанной машине
Размещение шеллкода в памяти
Обычный способ размещения шелл-кода в памяти — это использовать VirtualAlloc для выделения памяти с нужными разрешениями. Затем вредоносная программа использует RtlMoveMemory для записи шелл-кода в выделенное пространство. После чего создается поток для передачи элемента управления в это место.
Как извлечь шелл-код из памяти
Для извлечения шеллкода мы можем использовать хуки api. Обычно устанавливают точку останова при любом вызове API. Я буду использовать x64dbg. Вы можете использовать любое другое приложение.
Загрузите исполняемый файл в x64dbg. Перейдите к символам и найдите VirtualAlloc. Установите точку останова и выполняйте до возврата.
VirtualAlloc вернет адрес выделенной памяти. Он будет в регистре rax / eax. Это адрес, по которому вы найдете шеллкод.
Установите точку останова при вызове функции CreateThread. Третий аргумент будет адресом памяти, куда мы скопировали шеллкод.
Следуйте по адресу в дампе. Вот где находится шеллкод:
Давайте сравним шеллкод, найденный в памяти, с шелл-кодом в исходном коде. Первые три байта — это DA CB BB.
Да, совпадает. Этот метод можно использовать для извлечения распакованных / расшифрованных исполняемых файлов в память.
Еще по теме: Лучшие программы для реверс-инжиниринга
ВКонтакте
OK
Telegram
Viber
При вводе строки по CTRL+F в коде надо помнить, что внутри строчки не должно быть никаких тегов, например изменения шрифта или стиля, иначе строчка может и не найтись в поиске по тексту HTML кода.
Например текст на странице такой:
2х2=4
Это же самое в HTML коде выглядит так:
2х2=<strong>4</strong>
Поиск ничего не даст
Такое бывает в тех случаях когда внутри строки используются теги; в этом случае надо найти и скопировать строчку на экране, затем преобразовать в HTML (фрагмент кода для преобразования приведен в ответе на вопрос Какие есть толковые способы перевести doc в html?) и только потом, зная как закодирована строчка, можно искать этот код в коде HTML.
D
На сайте с 23.11.2008
Offline
120
15 февраля 2011, 15:39
10424
Взломали один сайт на дле. Судя по всему залили шелл, потому как уязвимости залатал все
Постоянно пихают ифреймы. Как найти этот шелл? Встроенные в дле антивирус сторонних файлов не нашел((
L
На сайте с 13.01.2011
Offline
114
15 февраля 2011, 16:14
#1
djos:
Взломали один сайт на дле. Судя по всему залили шелл, потому как уязвимости залатал все
Постоянно пихают ифреймы. Как найти этот шелл? Встроенные в дле антивирус сторонних файлов не нашел((
не помню где – но рекомендовали делать так: в ssh
cd /var/www
Запускам команду, которая рекурсивно ищет нехорошие файлы в папках /uploads/ на всех сайтах:
find -type f -wholename “*/uploads/*” -a -regex “.*(.php|.cgi|.pl|.php3|.php4|.php5|.php6|.phps|.phtml|.shtml)$” -print > shell.log
папка uploads нужна для хранения пользовательских файлов и не должна содержать скрипты.
Информация о найденных файлах будет записана в файл shell.log.
Поиск картинок, содержащих php-код в папке templates или ставишь свою папку
find -type f -wholename “*/templates/*” -a -regex “.*(.gif|.png|.jpg|.jpeg)$”|while read i;do cat “$i”|grep -l –label=”$i” “<?php”;done > shell.log
Поиск файлов с ифреймами:
find -type f -regex “.*(.php|.tpl|.lng|.html)$”|while read i;do cat “$i”|grep -H –label=”$i” “<iframe src=”http://”;done > shell.log
потом смотришь shell.log
Контакты-icq 535609 ()
M
На сайте с 16.09.2009
Offline
278
15 февраля 2011, 16:17
#2
djos:
Взломали один сайт на дле. Судя по всему залили шелл, потому как уязвимости залатал все
Постоянно пихают ифреймы. Как найти этот шелл?
Начать с того, что поискать “зверюшек” на своем ПК. Если его владелец любитель вареза и клубнички – весьма вероятно, что “пихают” как раз с него по FTP.
А вообще – тут нет телепатов. Никто Вам не скажет “как”, не посмотрев на ситуацию непосредственно на месте. Стоить такое будет недешево.
Абонементное сопровождение серверов (Debian)
Отправить личное сообщение (),
написать письмо ().
На сайте с 08.08.2007
Offline
111
15 февраля 2011, 16:22
#3
djos:
Встроенные в дле антивирус сторонних файлов не нашел((
первое что следует сделать – поменять пароль на ftp..
Администрирование, Linux, Cisco, Juniper
D
На сайте с 23.11.2008
Offline
120
15 февраля 2011, 16:28
#4
фтп я вообще вырубил….он там не нужен
M
На сайте с 16.09.2009
Offline
278
15 февраля 2011, 16:44
#5
djos:
фтп я вообще вырубил….он там не нужен
А как Вы файлы модифицируете? По SSH?
На сайте с 24.10.2008
Offline
174
15 февраля 2011, 16:59
#6
Наверно через панель.
. (#)
R
На сайте с 24.01.2008
Offline
180
15 февраля 2011, 17:17
#7
Стучите поможем
D
На сайте с 23.11.2008
Offline
120
15 февраля 2011, 19:31
#8
Пожалуйста платные услуги не предлагайте.
Файлы модифицирую по ссш или через панель
Logger спасибо…шел нашел но на другом сайте)) На том что нужно так и не нашол
На сайте с 30.11.2008
Offline
667
15 февраля 2011, 19:39
#9
для начала поискать файлы с датой, которая позже той, когда вы заливали или изменяли файлы движка
D
На сайте с 23.11.2008
Offline
120
15 февраля 2011, 23:12
#10
Это сложно….сайту уже не первый год…там даты всех файлов в расброс. Движок модифицирвал не раз модулями
Новичку очень трудно найти нужный символ или слово в массе кода, однако это делается очень быстро и просто. Если не знаете как, то читайте дальше.
В следующей статье, мы приступим к редактированию шаблона, и нам придётся находить нужные элементы в коде темы.
Если кто-то ещё не видел, что из себя представляет код шаблона, то зайдите в Консоль — Внешний вид — Редактор.
Перед Вами откроется код файла style.css. Покрутите его вниз, и первое, что придёт Вам в голову будет: ё-моё, как же в этой массе английских слов, цифр и символов, найти то, что нам будет нужно.
Для полноты ощущения, можно открыть один из php файлов, которые расположены в колонке справа от поля редактора.
Только сразу отгоните мысль типа: «Я в этом до самой смерти не разберусь». Разберётесь, и я Вам в этом помогу.
Рассмотрим два варианта, в зависимости от начальных условий, нахождения нужного элемента в коде.
Вариант 1.
Условие: мы точно знаем то, что нам нужно найти.
Для примера возьмём код страницы.
Комбинация клавиш Contrl-F откроет окно поиска в правом верхнем углу, в которое можно ввести искомый элемент кода. Элемент и все его повторения подсветятся.
Этот поиск работает абсолютно для любого кода, открытого в браузере, то есть на странице.
Вариант 2.
Условие: мы видим элемент на странице, но не знаем ни его html, ни css.
В этом случае потребуется web-инспектор, или по другому Инструмент разработчика.
Инструмент разработчика есть во всех браузерах и открыть его можно или клавишей F12, или правой клавишей мыши, выбрав “Просмотреть код” или “Исследовать элемент”. В разных браузерах по разному.
Главное не выбирайте “Просмотреть код страницы”. Похоже, но не то.
После этого появится web-инспектор. Его интерфейс в разных браузерах немного отличается, но принцип действия везде одинаковый.
Я покажу на примере web-инспектора Chrome.
Заходим на страницу и открываем web-инспектор. По умолчанию он откроется в двух колонках, в левой будет html код всех элементов, находящихся на странице, а в правой — css оформление.
Изначально, код откроется в сложенном виде, то есть будут видны только основные элементы страницы, но если щёлкнуть по треугольничку в начале строки, то откроются все вложения, находящиеся в элементе.
И вот так, открывая вложение за вложением, можно добраться практически до любого элемента, находящегося на странице.
Определить, какой код, какому элементу соответствует, очень просто.
Надо просто вести по строкам курсором, и как только курсор оказывается на строке с кодом, так тут-же элемент, которому соответствует этот код, подсвечивается.
Теперь найдём css этого элемента. Для этого надо один раз щёлкнуть левой клавишей по строке с html, и в правой колонке отобразятся все стили, которые ему заданы, а так-же стили, влияющие на элемент, от родительских элементов.
Теперь, зная class или id элемента, можно спокойно идти в файл style.css, найти в нём нужный селектор, с помощью Поиска (Ctrl+F), и править внешний вид элемента.
Желаю творческих успехов.
Неужели не осталось вопросов? Спросить
Перемена
— Мам, ну почему ты думаешь, что если я была на дне рождения, то сразу пила?!
— Дочь а нечего что я папа?
Объявление в метро: «при обнаружении подозрительных предметов сделайте подозрительное лицо.
В раздел > > > Исправляем шаблон WordPress. Веб-инспектор
Приветствую всех читателей этой статьи и посетителей <Codeby.net> 🖐
Хочу рассказать о шелл-кодах и особенностях их написания вручную. Вам понадобятся знания ассемблера на базовом уровне. Рассмотрим как пишут шелл-коды без инструментов, которые могут их автоматически создать. Вредоносные шелл-коды писать не будем! Будем писать псевдо шелл-коды для простоты и понимания. Если эта статья и её формат вам понравиться, тогда расскажу о вредоносных шелл-кодах
Написание шелл-кода будет показано для архитектуры x86. Алгоритм не сильно отличается для архитектуры x64. Для практики я рекомендую вам установить Linux в VirtualBox или VMware. Так же можно экспортировать готовый образ виртуальной машины.
План:
Теория: Что такое шелл-код и системные вызовы
Практика: Сравниваем программу на ассемблере и языке Си. Делаем hello world в виде шелл-кода
Что такое шелл-код и системные вызовы
Шелл-код — это двоичный исполняемый код, который выполняет определенную задачу. Например: Передать управление
Ссылка скрыта от гостей
(/bin/sh
) или даже выключить компьютер. Шелл-код пишут на языке ассемблер с помощью опкодов (Например: x90
означает команду:nop
).
Программы взаимодействуют с операционной системой через функции. Функции расположены в библиотеках. Функция printf()
, exit()
в библиотеке libc
. Помимо функций существуют системные вызовы. Системные вызовы находятся в ядре операционной системы. Взаимодействие с операционной системой происходит через системные вызовы. Функции используют системные вызовы.
Системные вызовы не зависят от версии какой-либо из библиотеки. Из-за универсальности системные вызовы используют в шелл-кодах.
У системных вызовов есть кода. Например, функция printf()
использует системный вызов write()
с кодом 4.
Машины с архитектурой x86: Системные вызовы определены в файле /usr/include/i386-linux-gnu/asm/unistd_32.h
Машины с архитектурой x64: Системные вызовы определены в файле /usr/include/x86_64-linux-gnu/asm/unistd_64.h
Ссылка скрыта от гостей
с объяснениями.
Проверим существование системных вызовов на практике
Напишем программу на языке Си, печатающую строку BUG.
Код:
C:
#include <stdio.h>
void main(void) { printf("BUG"); }
Компиляция: gcc printf_prog.c -o printf_prog
Проверим наличие системных вызовов с помощью команды: strace ./printf_prog
Вывод strace
C:
execve("./printf_prog", ["./printf_prog"], 0xbffff330 /* 48 vars */) = 0
brk(NULL) = 0x405000
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7fcf000
access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/etc/ld.so.cache", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=92992, ...}) = 0
mmap2(NULL, 92992, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb7fb8000
close(3) = 0
access("/etc/ld.so.nohwcap", F_OK) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_LARGEFILE|O_CLOEXEC) = 3
read(3, "177ELF11133313002541004"..., 512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1947056, ...}) = 0
mmap2(NULL, 1955712, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0xb7dda000
mprotect(0xb7df3000, 1830912, PROT_NONE) = 0
mmap2(0xb7df3000, 1368064, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19000) = 0xb7df3000
mmap2(0xb7f41000, 458752, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x167000) = 0xb7f41000
mmap2(0xb7fb2000, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1d7000) = 0xb7fb2000
mmap2(0xb7fb5000, 10112, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb7fb5000
close(3) = 0
set_thread_area({entry_number=-1, base_addr=0xb7fd00c0, limit=0x0fffff, seg_32bit=1, contents=0, read_exec_only=0, limit_in_pages=1, seg_not_present=0, useable=1}) = 0 (entry_number=6)
mprotect(0xb7fb2000, 8192, PROT_READ) = 0
mprotect(0x403000, 4096, PROT_READ) = 0
mprotect(0xb7ffe000, 4096, PROT_READ) = 0
munmap(0xb7fb8000, 92992) = 0
fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x88, 0), ...}) = 0
brk(NULL) = 0x405000
brk(0x426000) = 0x426000
brk(0x427000) = 0x427000
write(1, "BUG", 3BUG) = 3
exit_group(3) = ?
+++ exited with 3 +++
В конце strace мы можем видеть системный вызов write(1, "BUG", 3BUG)
. Количество кода для шелл-кода слишком много, если использовать функции. Старайтесь писать небольшие шелл-коды. Так они будут меньше обнаруживаться и вероятность их срабатывания будет больше.
Сравниваем программу на ассемблере и языке Си
Шелл-код можно написать, как программу на языке Си, скомпилировать, при необходимости отредактировать и перевести в байтовое представление. Такой способ подходит, если мы пишем сложный шелл-код.
Шелл-код можно написать на языке ассемблер. Этот способ я хочу рассмотреть более подробно. Для сравнения мы напишем 2 программы, печатающие сроку Hello world!. Первая будет написана на языке Си, а вторая на ассемблере.
Код на языке Си:
C:
#include <stdio.h>
void main(void) { printf("Hello, world!"); }
Компиляция: gcc hello_world_c.c -o hello_world_c
Код на ассемблере:
C-подобный:
global _start
section .text
_start:
mov eax, 4 ; номер системного вызова (sys_write)
mov ebx, 1 ; файловый дескриптор (stdout)
mov ecx, hello_world ; сообщение hello_world
mov edx, len_hello ; длина строки hello_world
int 0x80 ; вызов системного прерывания
mov eax, 1 ; номер системного вызова (sys_exit)
xor ebx, ebx ; Обнуляем регистр ebx, чтобы первый аргумент системного вызова sys_exit был равен 0
int 0x80 ; вызов системного прерывания
hello_world: db "Hello, world!", 10 ; 10 - количество выделенных байт для строки
len_hello: equ $ - hello_world ; вычиляем длину строки. $ указывает на строку hello_world
Получаем объектный файл с помощью nasm: nasm -f elf32 hello_world.asm -o hello_world.o
Объединяем объектный файл в один исполняемый: ld -m elf_i386 hello_world.o -o hello_world
В ассемблерном коде присутствует инструкция int 0x80. Это системное прерывание. Когда процессор получает прерывание 0x80
, он выполняет запрашиваемый системный вызов в режиме ядра, при этом получая нужный обработчик из Interrupt Descriptor Table (таблицы описателей прерываний). Номер системного вызова задаётся в регистре EAX. Аргументы функции должны содержаться в регистрах EBX, ECX, EDX, ESI, EDI и EBP. Если функция требует более шести аргументов, то необходимо поместить их в структуру и сохранить указатель на первый элемент этой структуры в регистр EBX.
Посмотрим на ассемблерный код получившихся файлов с помощью objdump
.
Функция main в программе на языке Си:
C-подобный:
1199: 8d 4c 24 04 lea ecx,[esp+0x4]
119d: 83 e4 f0 and esp,0xfffffff0
11a0: ff 71 fc push DWORD PTR [ecx-0x4]
11a3: 55 push ebp
11a4: 89 e5 mov ebp,esp
11a6: 53 push ebx
11a7: 51 push ecx
11a8: e8 24 00 00 00 call 11d1 <__x86.get_pc_thunk.ax>
11ad: 05 53 2e 00 00 add eax,0x2e53
11b2: 83 ec 0c sub esp,0xc
11b5: 8d 90 08 e0 ff ff lea edx,[eax-0x1ff8]
11bb: 52 push edx
11bc: 89 c3 mov ebx,eax
11be: e8 6d fe ff ff call 1030 <printf@plt>
11c3: 83 c4 10 add esp,0x10
11c6: 90 nop
11c7: 8d 65 f8 lea esp,[ebp-0x8]
11ca: 59 pop ecx
11cb: 5b pop ebx
11cc: 5d pop ebp
11cd: 8d 61 fc lea esp,[ecx-0x4]
11d0: c3 ret
Ассемблер:
C-подобный:
08049000 <_start>:
8049000: b8 04 00 00 00 mov eax,0x4
8049005: bb 01 00 00 00 mov ebx,0x1
804900a: b9 1f 90 04 08 mov ecx,0x804901f
804900f: ba 0e 00 00 00 mov edx,0xe
8049014: cd 80 int 0x80
8049016: b8 01 00 00 00 mov eax,0x1
804901b: 31 db xor ebx,ebx
804901d: cd 80 int 0x80
0804901f <hello_world>:
804901f: 48 dec eax
8049020: 65 6c gs ins BYTE PTR es:[edi],dx
8049022: 6c ins BYTE PTR es:[edi],dx
8049023: 6f outs dx,DWORD PTR ds:[esi]
8049024: 2c 20 sub al,0x20
8049026: 77 6f ja 8049097 <hello_world+0x78>
8049028: 72 6c jb 8049096 <hello_world+0x77>
804902a: 64 21 0a and DWORD PTR fs:[edx],ecx
Кажется, что больше кода в ассемблерном листинге, но это не так. В листинге языка Си я показал только функцию main, а она там не одна! В листинге ассемблера я показал программу целиком!
Делаем hello world в виде шелл-кода
Взгляните на листинг программы, написанной на ассемблере. Сначала идут адреса, затем байты, а далее инструкции (8049000: b8 04 00 00 00 mov eax, 0x4
). Запишем опкоды инструкций в виде шелл-кода.
Вручную всё делать очень не удобно. Bash нам в помощь: objdump -d ./hello_world|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr 't' ' '|sed 's/ $//g'|sed 's/ /\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g'
(вместо ./hello_world
можно подставить любую другую программу ).
Опкоды ( представлены в читаемом виде )
C:
"xb8x04x00x00x00"
"xbbx01x00x00x00"
"xb9x1fx90x04x08"
"xbax0ex00x00x00"
"xcdx80xb8x01x00"
"x00x00x31xdbxcd"
"x80x48x65x6cx6c"
"x6fx2cx20x77x6f"
"x72x6cx64x21x0a"
Но работать этот шелл-код не будет, так как в нём присутствуют байты x00
и строка hello_world указана по адресу ( "xb9x1f"x90x04x08"
– это инструкция mov ecx, 0x8040901f
), а в программе адрес может быть разный из-за механизма защиты
Ссылка скрыта от гостей
. В шелл-коде точных адресов быть не должно. Решим проблему постепенно, начав заменять данные, расположенные по точному адресу, а затем уберём байты x00
.
Убираем точные адреса
Строка, которую нам нужно напечатать – Hello, world! Представим её в виде байтов. Утилита xxd
нам поможет: echo "Hello, World!" | xxd -pu
Байтовое представление строки Hello, world!: 48656c6c6f2c20576f726c64210a
. Для удобства разделим по 4 всю последовательность байтов: 48656c6c 6f2c2057 6f726c64 210a
. Байтов в конце недостаточно. Во всех отделённых нами наборов байтов, их по 4, а в последнем всего лишь 2. Добавим любые байты кроме x00
, так как потом добавленные нами байты обрежутся программой. Я выберу байты x90
. Нам нужно расположить байты в порядке: little-enidan ( в обратном порядке ). Получится такая последовательность байт: 90900a21 646c726f 57202c6f 6c6c6548
. Это просто байты строки.
Теперь превратим их в инструкции на ассемблере. Тут нам поможет фреймворк
Ссылка скрыта от гостей
с утилитой rasm2.
Получаем опкоды инструкций
Bash:
rasm2 -a x86 -b 32 "push 0x90900a21"
rasm2 -a x86 -b 32 "push 0x646c726f"
rasm2 -a x86 -b 32 "push 0x57202c6f"
rasm2 -a x86 -b 32 "push 0x6c6c6548"
rasm2 -a x86 -b 32 "mov ecx, esp"
Флаг -a x86 -b 32 обозначают вывод для архитектуры x86.
Чтобы передать байты в стек нужна инструкция push
. Регистр [/COLOR]esp[COLOR=rgb(97, 189, 109)]
указывает на вершину стека. Переместим на значение вершине стека в регистр ecx
.
Команда PUSH размещает значение в стеке, т.е. помещает значение в ячейку памяти, на которую указывает регистр ESP, после этого значение регистра ESP увеличивается на 4.
Как будет выглядить код на ассемблере
C-подобный:
push 90900a21
push 646c726f
push 57202c6f
push 6c6c6548
mov ecx, esp
В итоге получаем: 68210a9090 686f726c64 686f2c2057 6848656c6c 89e1
. Заменим точный адрес в нашем шелл-коде на новые инструкции.
C:
"xb8x04x00x00x00"
"xbbx01x00x00x00"
"x68x21x0ax90x90"
"x68x6fx72x6cx64"
"x68x6fx2cx20x57"
"x68x48x65x6cx6c"
"x89xe1"
"xbax0ex00x00x00"
"xcdx80xb8x01x00"
"x00x00x31xdbxcd"
"x80x48x65x6cx6c"
"x6fx2cx20x77x6f"
"x72x6cx64x21x0a"
Замена нулевых байтов
Для удобства мы представим эти инструкции в виде ассемблерных команд. Нам поможет утилита ndisasm
. Первым делом запишем наши байты в файл, а затем применим утилиту ndisasm
.
Bash:
echo -ne 'xb8x04x00x00x00xbbx01x00x00x00x68x21x0ax90x90x68x6fx72x6cx64x68x6fx2cx20x57x68x48x65x6cx6cx89xe1xbax0ex00x00x00xcdx80xb8x01x00x00x00x31xdbxcdx80x48x65x6cx6cx6fx2cx20x77x6fx72x6cx64x21x0a' > test
ndisasm -b32 test
Вывод утилиты ndisasm
C-подобный:
00000000 B804000000 mov eax,0x4
00000005 BB01000000 mov ebx,0x1
0000000A 68210A9090 push dword 0x90900a21
0000000F 686F726C64 push dword 0x646c726f
00000014 686F2C2057 push dword 0x57202c6f
00000019 6848656C6C push dword 0x6c6c6548
0000001E 89E1 mov ecx,esp
00000020 BA0E000000 mov edx,0xe
00000025 CD80 int 0x80
00000027 B801000000 mov eax,0x1
0000002C 31DB xor ebx,ebx
0000002E CD80 int 0x80
00000030 48 dec eax
00000031 656C gs insb
00000033 6C insb
00000034 6F outsd
00000035 2C20 sub al,0x20
00000037 776F ja 0xa8
00000039 726C jc 0xa7
0000003B 64210A and [fs:edx],ecx
Инструкции, содержащие нулевые байты
C-подобный:
00000000 B804000000 mov eax,0x4
00000005 BB01000000 mov ebx,0x1
00000020 BA0E000000 mov edx,0xe
00000027 B801000000 mov eax,0x1
Нам нужно заменить инструкции с нулевыми байтами на другие. Нулевые байты образуются из-за того, что инструкция mov
– двухбайтовая, а оставшиеся 2 байта из 4 компилятору нужно заменить нулями. Предлагаю заменить эти инструкции mov на сочетание двухбайтовых инструкций xor
и mov
.
Ассемблерные инструкции и их опкоды
C-подобный:
xor eax, eax ; x31xc0
mov al, 4 ; xb0x04
xor ebx, ebx ; x31xdb
mov bl, 1 ; xb3x01
xor edx, edx ; x31xd2
mov dl, 14 ; xb2x0e
xor eax, eax ; x31xc0
mov al, 1 ; xb0x01
Итоговый вариант Hello, World! в виде шелл-кода
C-подобный:
"x31xc0xb0x04"
"x31xdbxb3x01"
"x68x21x0ax90x90"
"x68x6fx72x6cx64"
"x68x6fx2cx20x57"
"x68x48x65x6cx6c"
"x89xe1"
"x31xd2xb2x0e"
"xcdx80"
"x31xc0xb0x01"
"x31xdbxcd"
"x80x48x65x6cx6c"
"x6fx2cx20x77x6f"
"x72x6cx64x21x0a"
Оформим весь этот набор байтов в виде программы на языке Си.
Код программы
C:
unsigned char hello_world[]=
// Заменённые инструкции
//"xb8x04x00x00x00" mov eax,0x4
"x31xc0xb0x04"
//"xbbx01x00x00x00" mov ebx,0x1
"x31xdbxb3x01"
"x68x21x0ax90x90"
"x68x6fx72x6cx64"
"x68x6fx2cx20x57"
"x68x48x65x6cx6c"
"x89xe1"
//"xbax0ex00x00x00" mov edx,0xe
"x31xd2xb2x0e"
"xcdx80"
//"xbax01x00x00x00" mov eax,0x1
"x31xc0xb0x01"
"x31xdbxcd"
"x80x48x65x6cx6c"
"x6fx2cx20x77x6f"
"x72x6cx64x21x0a";
void main() {
int (*ret)() = (int(*)())hello_world;
ret();
}
Ссылка скрыта от гостей
Компилируем: gcc hello_world_test.c -o hello_world_test -z execstack
Проверяем работоспособность: ./hello_world_test
Довольно долго это всё делать, если вы не хотите делать шелл-код для атаки на определённую компанию.
Существует замечательный инструменты Msfvenom и подобные ему. Msfvenom позволяет делать шелл-код по шаблону и даже закодировать его. Про этот инструмент и про сам metasploit на Codeby.net написано много информации. Про энкодеры информации в интернете тоже достаточно. Например:
Ссылка скрыта от гостей
.
Хочу порекомендовать сайты:
Ссылка скрыта от гостей
и
Ссылка скрыта от гостей
. На этих сайтах вы сможете найти множество шелл-кодов.
Желаю вам удачи и здоровья. Не болейте и 🧠прокачивайте мозги🧠.