Проверка lua кода на ошибки

Разработчики давно поняли: чтобы сделать программу по-настоящему гибкой и расширяемой, нужно добавить внутрь хороший скриптовый язык. Тем более что придумывать ничего не надо: есть Lua, который прекрасно интегрируется, чем и воспользовались создатели Wireshark, Nmap и даже малвари.

WARNING

Intro

Хакер #179. Интернет вещей — новый вектор атак

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

Расширение для Wireshark

В работе мне довольно часто приходится анализировать большие объемы трафика, причем искать в них вполне конкретные паттерны. Поддержка Lua для написания расширений в Wireshark может сэкономить кучу времени (которую можно потратить, скажем, на сон).

При небольшой сноровке можно писать довольно сложные сценарии для поиска паттернов и анализа трафика. Но для примера мы возьмем что-нибудь простое и показательное — напишем простой скрипт для парсинга полей имени хоста и cookies. И параллельно разберем несколько ошибок, которые могут возникнуть в процессе разработки расширения.

Пример выполнения Lua-скрипта в Wireshark

Пример выполнения Lua-скрипта в Wireshark

Скрипт также можно выполнить через консоль, используя tshark:

Так как скрипт небольшой, я приведу код сразу, а далее мы его разберем по частям:

Итак, поехали. Сначала для более удобного вывода нужных нам данных создадим отдельное окно для текстовой информации:

В принципе, можно уже выполнить эту строку после запуска Wireshark, и мы получим желанное окно, которое представлено на скриншоте.

Созданное окно с помощью расширения в Wirehark

Созданное окно с помощью расширения в Wirehark

Далее создадим переменные, которые будут обращаться к полям host и cookie HTTP-протокола:

Таким образом можно обращаться к любым полям любого протокола, а как мы все помним, этот замечательный снифер из коробки знает структуру колоссального числа протоколов и умеет «молотить» их на понятные части на лету (впрочем, для неизвестного протокола легко прописать структуру).

Теперь напишем функцию инициализации приемника пакетов и установим фильтр на HTTP-протокол:

Далее все совсем просто, переводим в строки полученные переменные и добавляем к созданному окну:

Единственный нюанс: объединить переменные с помощью операции объединения строк нельзя, поскольку такие данные имеют тип userdata, а Lua не может напрямую их изменять. Но это можно обойти через метатаблицы.

Теперь выполним наш скрипт и запустим снифинг пакетов.

Работа нашего расширения в Wireshark

Работа нашего расширения в Wireshark

Работает! Но как видишь, у расширения есть минус — он выводит одинаковые кукисы, поэтому в идеале надо сделать таблицу, где будут храниться старые значения, и добавить проверку на уникальность. Но это я оставляю тебе в качестве домашнего задания. Если же ты не справишься или ты из тех людей, которые любят готовые рецепты, то полная версия будет ждать тебя на моем GitHub-аккаунте.

В сноске ты найдешь ссылки на вики и API с более подробной информацией по написанию расширений. Помимо этого, приведены примеры рабочих скриптов, один из которых сохраняет VoIP-звонки из пакетов в отдельные файлы и работает с SQL базой данных.

Расширение для Nmap

Разберем стандартную структуру скрипта. В начале каждого сценария добавляются стандартные библиотеки:

Далее идут метаданные:

После этого идет непосредственно код сценария. Для примера напишем простейший скрипт для брута пользователей популярной CMS LiveStreet.

Вначале определим стандартные переменные и подключим недостающие библиотеки:

Далее составим класс Driver для брута из соответствующей библиотеки. Напишем функцию инициализации с указанием хоста, порта и пути до формы логина:

Функции коннекта и дисконнекта оставим без изменений:

Далее пишем проверку, чтобы посмотреть успешность коннекта и наличие поля для пароля:

Ну и самая главная часть — функция логина. Сначала составляем HTTP-запрос:

Далее указываем результат, после которого считается, что пара логин с паролем, переданные в запросе, были правильными:

В случае с сайтами на WordPress значение будет 302. Другой вариант — проверять появление нового HTML-элемента на странице (например, после логина обязательно появится ссылка для выхода пользователя из системы):

Сохраним полученный скрипт с расширением nse и положим рядом два файла: users. txt и passwords. txt — с некоторым количеством имен пользователей и паролей. В случае LiveStreet можно даже напарсить валидные имена пользователей или добавить этот функционал в скрипт.

Теперь запустим полученный сценарий (полный исходник скрипта можно скачать из моего GitHub-репозитория):

Если все пройдет успешно, то ты увидишь отчет о проделанном брутфорсе.

Отчет Nmap-скрипта для брута пользователей LiveStreet CMS

Отчет Nmap-скрипта для брута пользователей LiveStreet CMS

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

Шпаргалка по Lua

Первое, что надо знать, — Lua — это язык с динамическим определением данных, то есть переменные получают тип на лету в зависимости от своего содержания. Всего используется восемь типов:

Условные операторы и циклы довольны стандартны:

Операции также почти все знакомые:

Функцию мы рассмотрим на примере тестового скрипта в нашей программе. Более подробно про этот язык можешь прочитать по ссылкам в сносках. Для написания программ достаточно будет Notepad++ или Sublime Text.

Outro

Вообще, использование Lua растет и растет. Так, на момент написания статьи была опубликована новость, что появился плагин для Olly Debugger версии 2+, добавляющий поддержку Lua.

Впрочем, язык не ограничивается одними программами для ИБ-сферы и может пригодиться в самых разных ситуациях. Как я уже говорил, его часто используют для игр, например World of Warcraft в своих аддонах (предоставляя API и довольно неплохую документацию по нему). Помимо игровых приложений, его задействуют такие программы, как Setup Factory. На нем написаны многие инсталляторы: Apache, nginx, Adobe Photoshop Lightroom, VLC и многие другие. Там, где нужно реализовать программируемое поведение программы, — интегрированный интерпретатор Lua точно будет очень неплохим вариантом.

Встраиваем компилятор в свою программу

Итак, главная фишка Lua в том, что его можно встроить в любую программу и предложить всем желающим расширить ее возможности. Как это сделать? Я покажу на примере Visual C++ программы. Стоит отметить, что сам Lua написан на чистом C, и это создает некоторые сложности при добавлении в программы с плюсами. На просторах Сети предлагается несколько вариантов добавления поддержки Lua в C++ программы. Кто-то предпочитает скачивать уже прекомпилированные библиотеки или готовые фреймворки, кто-то — компилировать из исходников самому, а кто-то — подключать исходники к своему проекту и, немного разобравшись с настройками в проекте, добиться действительного добавления Lua в свою программу. Мы с тобой как раз и разберем последний вариант.

Создадим новый консольный проект (я пользуюсь Visual Studio 2010). После чего добавим через свойства проекта директорию с исходниками:

где в каждом из разделов добавим в соответствующие поля MARKDOWN_HASHd8a960f245cb01e9a35ba16cf2a54fe6MARKDOWN_HASH путь к исходникам языка. Далее создаем раздел Lua, куда добавляем все файлы из папки MARKDOWN_HASH25d902c24283ab8cfbac54dfa101ad31MARKDOWN_HASH :

Добавление директории с исходниками Lua в проект

Добавление директории с исходниками Lua в проект.

Как я уже упомянул выше, Lua написан на чистом C, поэтому применим небольшой хак — добавим в начало своего файла следующие строки:

Далее инициализируем наш язык и подключим его библиотеки:

Теперь создадим цикл, который будет проверять входящие данные, пока они не закончатся (или не переполнят буфер), и выполнять их:

Теперь можно компилировать проект и запустить.

Работаем в скомпилированном интерпретаторе Lua

Работаем в скомпилированном интерпретаторе Lua
В ходе компиляции могут возникнуть ошибки:

Следующий проект создадим аналогичный первому, но теперь будем запускать свои сохраненные скрипты в самой программе, инициализируем Lua и добавим после:

Это и есть обещанный пример объявления и работы с функцией. Теперь загрузим его в память и выполним:

Теперь рассмотрим возможность вызова функций C-программы из Lua-скриптов. И для начала объявим функцию, которая будет вызываться из нашего языка:

Далее регистрируем функцию:

Прописываем функцию, которая загружает по переданному пути скрипт:

И запускаем загруженный скрипт:

Но, если заметил, вызов немного отличается от предыдущего проекта. Константа MARKDOWN_HASH5301b763e99f84122b8de40237a602d5MARKDOWN_HASH используется вместе с функцией MARKDOWN_HASHeb8e633c3ab4c927bba1d52e54fb33c3MARKDOWN_HASH для подсчета стека до и после вызова. Компилируем, не забывая про описанные выше ошибки.

Теперь пропишем вызов этой функции из Lua в отдельный скрипт и назовем его MARKDOWN_HASH21b648082b7edb48f91278eceb83c54aMARKDOWN_HASH :

Вызовем полученный файл из нашей программы:

И получим следующий вывод в консоль:

Вывод вызываемой C-функции из Lua

Вывод вызываемой C-функции из Lua
Готовые исходники проектов ты можешь взять из GitHub, но не забывай, что в них прописаны пути к моей Lua и для экономии места вырезаны функции обработки ошибок Lua-скриптов. Еще я не подробно расписал одну интересную тему — работу со стеком, которая позволяет обмениваться данными с основной программой, хотя главное мы затронули в последнем проекте.

Борис dukeBarman Рютин

Известный реверсер (@dukebarman), докладчик на множестве конференций, постоянный автор «Хакера» и большой фанат вселенных Blizzard. В данный момент работает руководителем проектов в «Digital Security» (@DSecRU).

Источники:

https://xakep. ru/2014/09/05/lua-for-pentest/

Понравилась статья? Поделиться с друзьями:
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: