Как найти шел в коде

Как извлечь шеллкод из памяти

Форензика
1,812

Как извлечь шелл-код из памяти

Вредоносные программы иногда запускают шеллкод прямо в памяти. В этой небольшой статье я покажу, как извлечь шеллкод из памяти.

Еще по теме: Как обнаружить шелл-кoд на взломанной машине

Размещение шеллкода в памяти

Обычный способ размещения шелл-кода в памяти — это использовать VirtualAlloc для выделения памяти с нужными разрешениями. Затем вредоносная программа использует RtlMoveMemory для записи шелл-кода в выделенное пространство. После чего создается поток для передачи элемента управления в это место.

Размещение шеллкода в памяти

Размещение шеллкода в памяти

Как извлечь шелл-код из памяти

Для извлечения шеллкода мы можем использовать хуки api. Обычно устанавливают точку останова при любом вызове API. Я буду использовать x64dbg. Вы можете использовать любое другое приложение.

Загрузите исполняемый файл в x64dbg. Перейдите к символам и найдите VirtualAlloc. Установите точку останова и выполняйте до возврата.

Извлечь шелл-код из памяти

VirtualAlloc вернет адрес выделенной памяти. Он будет в регистре rax / eax. Это адрес, по которому вы найдете шеллкод.

Извлечение шеллкода из памяти

Установите точку останова при вызове функции CreateThread. Третий аргумент будет адресом памяти, куда мы скопировали шеллкод.

Сравните выделенное значение с EAX

Сравните выделенное значение с EAX

Следуйте по адресу в дампе. Вот где находится шеллкод:

Это шеллкод в памяти

Шеллкод

Давайте сравним шеллкод, найденный в памяти, с шелл-кодом в исходном коде. Первые три байта — это DA CB BB.

Шеллкод в памяти

Да, совпадает. Этот метод можно использовать для извлечения распакованных / расшифрованных исполняемых файлов в память.

Еще по теме: Лучшие программы для реверс-инжиниринга

ВКонтакте

Twitter

Facebook

OK

Telegram

WhatsApp

Viber

При вводе строки по CTRL+F в коде надо помнить, что внутри строчки не должно быть никаких тегов, например изменения шрифта или стиля, иначе строчка может и не найтись в поиске по тексту HTML кода.

Например текст на странице такой:

2х2=4

Это же самое в HTML коде выглядит так:

2х2=<strong>4</stron­g>

Поиск ничего не даст

Такое бывает в тех случаях когда внутри строки используются теги; в этом случае надо найти и скопировать строчку на экране, затем преобразовать в 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)
Отправить личное сообщение (),
написать письмо ().

Zaqwr

На сайте с 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?

Trafikgon

На сайте с 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 спасибо…шел нашел но на другом сайте)) На том что нужно так и не нашол

vandamme

На сайте с 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 в виде шелл-кода

1611680387761.png

Что такое шелл-код и системные вызовы

Шелл-код — это двоичный исполняемый код, который выполняет определенную задачу. Например: Передать управление

Ссылка скрыта от гостей

(/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!. Первая будет написана на языке Си, а вторая на ассемблере.

1611680968874.png

Код на языке Си:

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.

Убираем точные адреса

1611681224261.png

Строка, которую нам нужно напечатать – 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 написано много информации. Про энкодеры информации в интернете тоже достаточно. Например:

Ссылка скрыта от гостей

.
Хочу порекомендовать сайты:

Ссылка скрыта от гостей

и

Ссылка скрыта от гостей

. На этих сайтах вы сможете найти множество шелл-кодов.

Желаю вам удачи и здоровья. Не болейте и 🧠прокачивайте мозги🧠.

Добавить комментарий