Горячее
Лучшее
Свежее
Подписки
Сообщества
Блоги
Эксперты
Войти
Забыли пароль?
или продолжите с
Создать аккаунт
Я хочу получать рассылки с лучшими постами за неделю
или
Восстановление пароля
Восстановление пароля
Получить код в Telegram
Войти с Яндекс ID Войти через VK ID
Создавая аккаунт, я соглашаюсь с правилами Пикабу и даю согласие на обработку персональных данных.
ПромокодыРаботаКурсыРекламаИгрыПополнение Steam
Пикабу Игры +1000 бесплатных онлайн игр
Это захватывающая 2D рогалик, аркадный шутер и динамичная игра. Исследуйте уникальные уровни, уничтожайте врагов, собирайте монеты и прокачивайте своего персонажа.

Подземелье дизлайков

Экшены, Аркады, Шутер

Играть

Топ прошлой недели

  • Rahlkan Rahlkan 1 пост
  • Tannhauser9 Tannhauser9 4 поста
  • alex.carrier alex.carrier 5 постов
Посмотреть весь топ

Лучшие посты недели

Рассылка Пикабу: отправляем самые рейтинговые материалы за 7 дней 🔥

Нажимая кнопку «Подписаться на рассылку», я соглашаюсь с Правилами Пикабу и даю согласие на обработку персональных данных.

Спасибо, что подписались!
Пожалуйста, проверьте почту 😊

Помощь Кодекс Пикабу Команда Пикабу Моб. приложение
Правила соцсети О рекомендациях О компании
Промокоды Биг Гик Промокоды Lamoda Промокоды МВидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
0 просмотренных постов скрыто
2027
Ivannapa
Ivannapa
3 месяца назад

А большего мне и не надо⁠⁠

Жаба Отдых на природе Отдых Гамак Видео Вертикальное видео Короткие видео Реверс Видеомонтаж Громко
113
474
HerVamDam
HerVamDam
3 месяца назад
Юмор для всех и каждого

Ответ на пост «Честно украдено»⁠⁠2

Короткие видео Дети Печь Юмор Вертикальное видео Видео Без звука Ответ на пост Реверс
58
7
demaskir
demaskir
3 месяца назад
Таверна "На краю вселенной"
Серия Джетлаг

Сероглазый король⁠⁠

В толчее у фруктов, где оставили свежий хлеб, так и не довезённый до своей полки, удачно схватила брошенку. Полный пакет мандаринов, собранный кем-то ну прям для меня. И оставленный в ящике с бурыми в чёрный крап помидорами... Обычно я так не делаю, но народ, оголодавший после январских, душил необыкновенно. Да и душнил через край, препираясь друг с другом, с кассирами, дёргая всемогущую Галю с отменой поминутно. А тут ещё один мужик кокнул главный мем этой зимы — золотые яйца. Держась за минералку, будто за библейский посох, выронил из рук три коробки. Оплатил как миленький, не охнул, бессловесно. И буквально все посмотрели на него с уважением...

Выбрасывая дома покупки в пародии на магазную ленту, сверялась с чеком, хмуря брови. Когда, спохватившись в тревоге за морщинки, бровки развела, лобик разгладила, то увидела топающий по столу бумажный пакет. Мандарины от него уже разбежались, так что пакет, логично, ходил пустым. Сам по себе и по моему столу. Нелогично.. Я признала поражение морщин перед возможным инфарктом и принялась активно орать с нехорошо изумлённым лицом. Пакет, преисполнившись сочувствия (или акустического ужаса), откинулся. Передо мной, держащей дуршлаг и рукавицу для духовки, предстала небольшая черепаха. Вся серая, нежно-жемчужная под кухонным абажуром, с задранной мордочкой, дорожащей каждой своей морщинкой. И с удивительными влажно-серыми глазами, перлами редких раковин.

Я орать и психически устала, и связки уже не те, всё-таки в школе давно не работаю, практики не хватает. Отложив дуршлаг, проверив (точно ли теперь он пустой или там ещё кобра с факиром, но портала в цирк не нашла) пакет в жаропрочной варежке, я общипала второй вязкой рукой салат, купленный в горшке. Перенесла вспотевшей варежкой животное, скрывшееся внутрь, на подоконник, под лаковый пейзаж из полной луны на ясно-морозном небе. Положила листья перед панцирем, казавшимся без рожицы и ножек совсем декоративным. И вышла в комнату, чтоб не смущать гостя, уже под смачное чавканье, воображая, что напишу в Книгу жалоб и предложений. Предлагаю, мол, обмен: у меня черепашка в мандаринах, у кого кролик в капусте или хомяк в кураге?

На стрессе у меня активизировались отделы мозга, отвечающие за знания о черепахах.. Ничтожные крупицы информации были не более странными, чем сама ситуация. Черепашки-ниндзя, поедающие пиццу, смешивались с пляжами слоновьих черепах. Ну, мы не на Галапагоссах всё же, эта хотя бы мелкая, там мандаринов было-то на два кило.. А вдруг, прошибло меня, она вообще водоплавающая, может, хоть раковину набрать? Не, скоропалительный вывод! Надо сперва сфотографировать и поискать, что за особа-особь лопает сейчас мой салат.

В кухне, знакомый звук, с грохотом подвинули стул! К себе, вынув из-под стола. Я приготовилась заорать на бегу, набрала уж воздуха, да так обомлела, что чуть не лопнула. За столом сидел ничуть не одетый мужчина. С прежним чавканьем он трескал колбасу, откусывая от двух батонов сразу: колбасного и хлебного... Повернул ко мне лицо вождя или гуру, с точёными морщинами и пергаментной кожей, поднял печальные серые глаза родниковой прозрачности. И сказал. Членораздельно, по-русски, с распевным нажимом на "О":
— Не волнуйтесь! Полнолуние просто, а я оборотень наоборот. Превращаюсь в человека из черепахи.. Нонсенс, конечно.. Я до утра побуду у вас? А утром вы передайте меня моему человеку, я дам адрес. Я покушаю ещё, можно? Колбаса замечательная!

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

Шла пешком домой, игноря телефон и морщины между слезящимися глазами, всё повторяя про себя:
— А за окном шелестят тополя:
«Нет на земле твоего короля…»*

*Анна Ахматова "Сероглазый король", 1910

Показать полностью
[моё] Авторский рассказ Паранормальное Реверс Юмор Лирика Текст
0
274
SweetMatpeiiika
SweetMatpeiiika
4 месяца назад
Юмор и мемы

Так вот откуда кусты берутся!⁠⁠

Юмор Кусты Реверс Видео Без звука Короткие видео
18
507
buhanka.chan
buhanka.chan
4 месяца назад
Юмор для всех и каждого

Ответ на пост «Мы что-то такое всегда подозревали»⁠⁠2

@ArNikich, готово.

Юмор Политика Дональд Трамп Владимир Жириновский Видео Вертикальное видео Короткие видео Нейровидео Нейронные сети Ответ на пост Реверс Повтор
17
6
5igorsk
5igorsk
4 месяца назад

Реверс русалка⁠⁠

Реверс русалка Картинка с текстом, Кентавр, Комментарии, Реверс, Странный юмор, Повтор
Показать полностью 1
Картинка с текстом Кентавр Комментарии Реверс Странный юмор Повтор
2
75
Catslikeme
Catslikeme
4 месяца назад
Кусь
Серия Котики 2

Просто очень щедрые и заботливые коты⁠⁠

Вертикальное видео Кот Толстые котики Кошатники Пушистые Юмор Видео Короткие видео Реверс Повтор
4
2
0sadchi
0sadchi
5 месяцев назад
Лига Разработчиков Видеоигр

Как создать скрипт-beautifier в Ghidra на Python?⁠⁠

Как создать скрипт-beautifier в Ghidra на Python? Программирование, Python, Гайд, Windows, Реверс, Длиннопост

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

Если вы уже имели опыт работы с дизассемблером, то заметили, что читать его вывод не так легко, если целью является понять более высокие абстракции, заложенные в нём. Возможно, вы даже пытались декомпилировать его в псевдокод, но работать с переменными типа local_1-999 – то ещё удовольствие. Да, можно щёлкнуть на каждую из них и присвоить имя на основе логики. А что, если у вас 2000 строк и более?

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

Все манипуляции были проделаны на версии 11.1.2. Чтобы попасть в список доступных скриптов, откройте меню Window → Script Manager и там же создайте новый скрипт, нажав в правом верхнем углу кнопку Create New Script и выбрав язык Python.

Важное ограничение: Ghidra использует внутреннюю реализацию языка Python версии 2.7.

Пишем код.

Первым делом, нужно объявить кодировку, чтобы не получить кучу ошибок о наличии не-ASCI символов

# -*- coding: utf-8 -*-

Указываем, что исходный файл сохранён в кодировке UTF-8 (поддержка Unicode символов).

from ghidra.util.task import Task

Импортируем класс Task из модуля Ghidra, который позволяет создавать задачи для выполнения операций в фоне.

from ghidra.app.decompiler import DecompInterface

Импортируем интерфейс декомпилятора, позволяющий получать C-подобный код из бинарных данных.

from ghidra.util.task import ConsoleTaskMonitor

Импортируем класс ConsoleTaskMonitor для отслеживания прогресса выполнения задач с выводом в консоль.

from ghidra.program.model.symbol import SourceType, SymbolType

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

from ghidra.program.model.pcode import HighFunctionDBUtil

Импортируем утилиты для работы с высокоуровневым представлением функции (HighFunction) в базе данных Ghidra.

from ghidra.program.model.pcode.HighFunctionDBUtil import ReturnCommitOption

Импортируем опцию фиксации (commit) изменений в базе данных при обновлении параметров функции.

from java.awt import BorderLayout

Импортируем менеджер компоновки BorderLayout для организации компонентов в окне Java.

from javax.swing import JButton, JFrame, JTextArea, JScrollPane, JPanel

Импортируем стандартные Swing-компоненты: кнопку, окно, текстовую область, панель прокрутки и панель для построения GUI.

import re

Импортируем модуль регулярных выражений для поиска и обработки строк.

class RenameDialog(JFrame):

Объявляем класс RenameDialog, наследующийся от JFrame. Он представляет окно диалога для ввода новых имён.

def __init__(self, suggestions):

Конструктор класса, принимающий список предложенных имен (suggestions) для переименования.

JFrame.__init__(self, "Advanced Renamer")

Инициализируем базовый класс JFrame, задавая заголовок окна “Advanced Renamer”.

self.setSize(800, 600)

Устанавливаем размер окна – 800 пикселей по ширине и 600 по высоте.

self.setLayout(BorderLayout())

Задаём менеджер компоновки BorderLayout для организации компонентов внутри окна.

self.text_area = JTextArea()

Создаём текстовую область, в которой пользователь сможет редактировать имена.

self.text_area.setText("# Format: old=new\n" + "\n".join(suggestions))

Заполняем текстовую область начальным текстом с примером формата и списком предложенных имён, разделённых переносами строк.

scroll_pane = JScrollPane(self.text_area)

Создаём панель прокрутки, содержащую нашу текстовую область, чтобы можно было просматривать длинный текст.

self.add(scroll_pane, BorderLayout.CENTER)

Добавляем панель прокрутки в центр окна (согласно BorderLayout).

button_panel = JPanel()

Создаём панель для размещения кнопок в окне.

self.apply_btn = JButton("Apply", actionPerformed=lambda _: self.setVisible(False))

Создаём кнопку “Apply” с обработчиком события: при нажатии окно будет скрыто (setVisible(False)).

button_panel.add(self.apply_btn)

Добавляем кнопку “Apply” на панель кнопок.

self.add(button_panel, BorderLayout.SOUTH)

Размещаем панель кнопок в нижней части окна.

class AdvancedRenamer(Task):

Объявляем класс AdvancedRenamer, наследующийся от Task. Он отвечает за логику переименования символов в Ghidra.

def __init__(self, program, function):

Конструктор класса принимает объект программы (program) и функцию (function), над которой будет производиться переименование.

super(AdvancedRenamer, self).__init__("Advanced Renamer", True, False, True)

Вызываем конструктор базового класса Task, задавая имя задачи и некоторые флаги (например, показывать прогресс, отменяемость и т.д.).

self.program = program

Сохраняем ссылку на текущую программу Ghidra.

self.function = function

Сохраняем ссылку на функцию, которую собираемся анализировать и переименовывать.

self.monitor = ConsoleTaskMonitor()

Создаем экземпляр монитора задач, который выводит статус выполнения в консоль.

self.skipped = {'int', 'char', 'void', 'return', 'break', 'float'}

Определяем множество ключевых слов, которые не будут изменяться при переименовании (например, базовые типы и управляющие конструкции).

def find_and_rename(self, old_name, new_name):

Определяем метод для поиска символа с именем old_name и его переименования в new_name.

decompiler = DecompInterface()

Создаём экземпляр интерфейса декомпилятора.

decompiler.openProgram(self.program)

Открываем текущую программу в декомпиляторе для дальнейшей работы.

results = decompiler.decompileFunction(self.function, 60, self.monitor)

Декомпилируем функцию с таймаутом 60 секунд, используя монитор для отслеживания прогресса.

if results.decompileCompleted():

Проверяем, успешно ли завершилась декомпиляция.

hfunction = results.getHighFunction()

Получаем высокоуровневое представление функции (HighFunction) из результатов декомпиляции.

signatureSrcType = self.function.getSignatureSource()

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

HighFunctionDBUtil.commitParamsToDatabase(hfunction, True, ReturnCommitOption.COMMIT, signatureSrcType)

Фиксируем изменения параметров функции в базе данных, используя указанные опции. Это необходимо для того, чтобы локальные имена, такие как lVar1, uVar2, pVar3, были согласованы с базой данных, потому, что они генерируются самим декомпилятором и просто выводятся на экран, без коммита в базу.

if old_name.startswith("FUN_"):

Если имя символа начинается с “FUN_”, считаем его именем функции.

return self.rename_function(old_name, new_name)

Вызываем метод для переименования функции.

elif old_name.startswith(("DAT_", "PTR_", "UNK_", "LAB_")):

Если имя начинается с “DAT_”, “PTR_”, “UNK_” или “LAB_”, обрабатываем его как метку или данные. Покаяние: У меня так и не получилось дать ума PTR_ и UNK_, хоть это и глобальные имена, как DAT_ и LAB_, они не переименовываются данной функцией, но я оставил их как есть :з

return self.rename_label(old_name, new_name)

Вызываем метод для переименования метки.

elif old_name.startswith(("local_", "param_", "uVar", "lVar")):

Если имя соответствует шаблону локальной переменной или параметра, то…

return self.rename_local_variable(old_name, new_name)

… вызываем метод для переименования локальной переменной.

else:

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

return self.rename_local_variable(old_name, new_name)

Вызываем метод для переименования локальной переменной.

def rename_function(self, old_name, new_name):

Определяем метод, который переименовывает функцию с именем old_name в new_name.

try:

Начинаем блок обработки исключений, чтобы избежать сбоев при ошибках.

addr_str = old_name[4:] if old_name.startswith("FUN_") else old_name

Если имя начинается с “FUN_”, удаляем этот префикс, чтобы получить строку адреса функции.

addr = toAddr("0x{}".format(addr_str))

Преобразуем строку с адресом в объект адреса Ghidra, добавляя префикс “0x”.

func = getFunctionAt(addr)

Получаем объект функции, расположенной по данному адресу.

if func and func.getName() == old_name:

Если функция найдена и её имя соответствует old_name, то…

func.setName(new_name, SourceType.USER_DEFINED)

… устанавливаем новое имя для функции, указывая, что оно задано пользователем (USER_DEFINED).

except: pass

Если возникает ошибка (например, неверный адрес), просто игнорируем её.

def rename_label(self, old_name, new_name):

Определяем метод для переименования метки или символа, представляющего данные.

try:

Начинаем блок обработки исключений.

addr_str = old_name[4:] if old_name.startswith(("LAB_", "DAT_", "PTR_", "UNK_")) else old_name

Извлекаем адрес метки, убирая префикс (например, “LAB_”) если он присутствует.

addr = toAddr(addr_str)

Преобразуем строку адреса в объект адреса Ghidra.

for sym in self.program.getSymbolTable().getSymbols(addr):

Перебираем все символы, зарегистрированные по этому адресу, из таблицы символов программы.

if sym.getName() == old_name:

Если имя символа совпадает с old_name, то…

sym.setName(new_name, SourceType.USER_DEFINED)

… устанавливаем новое имя для символа с типом источника USER_DEFINED.

return True

Возвращаем True, указывая, что переименование прошло успешно.

except: pass

При возникновении исключения игнорируем его.

def rename_local_variable(self, old_name, new_name):

Определяем метод для переименования локальной переменной или параметра.

try:

Начинаем блок обработки исключений.

if new_name.lower() in self.skipped:

Если новое имя (в нижнем регистре) содержится в списке ключевых слов для пропуска, то…

return False

… прекращаем переименование, возвращая False.

# Далее идет блок, необходимый для обработки параметров

for param in self.function.getParameters():

Перебираем все параметры текущей функции.

if param.getName() == old_name:

Если имя параметра совпадает с old_name, то…

param.setName(new_name, SourceType.USER_DEFINED)

… устанавливаем новое имя для параметра.

# Local variables (даже если наш пациент был найдет среди параметров

# необходимо пройтись и по локальным переменным,

# иначе они не переименовываются, возможно надо тут просто

# сделать коммит в базу)

decompiler = DecompInterface()

Создаём новый экземпляр декомпилятора для обработки локальных переменных.

decompiler.openProgram(self.program)

Открываем программу в декомпиляторе.

results = decompiler.decompileFunction(self.function, 60, self.monitor)

Декомпилируем функцию с таймаутом 60 секунд.

if results.decompileCompleted():

Если декомпиляция прошла успешно, то…

hfunction = results.getHighFunction()

… получаем высокоуровневое представление функции.

syms = hfunction.getLocalSymbolMap().getSymbols()

Получаем список локальных символов (переменных) из высокоуровневой функции.

for sym in syms :

Перебираем каждый локальный символ.

if sym.getName() == old_name and sym.getName() != new_name:

Если имя символа совпадает с old_name и ещё не равно new_name, то…

HighFunctionDBUtil.updateDBVariable(sym, new_name, None, SourceType.USER_DEFINED)

… обновляем имя переменной в базе данных с новым именем и источником USER_DEFINED.

return True

Возвращаем True после успешного переименования локальной переменной.

return False

Если ни один из блоков не сработал, возвращаем False – переименование не выполнено.

except Exception as e:

Ловим исключения и сохраняем их в переменной e для отладки.

print("Error: {} -> {} ({})".format(old_name, new_name, str(e)))

Выводим сообщение об ошибке с указанием старого и нового имени, а также текста ошибки. Обратите внимание на форматирование строки, т.к. это Python 2.7.

return False

Возвращаем False, сигнализируя, что произошла ошибка при переименовании.

def run(self):

Определяем метод run, который является точкой входа при выполнении задачи AdvancedRenamer.

decompiler = DecompInterface()

Создаем экземпляр декомпилятора для работы с функцией.

decompiler.openProgram(self.program)

Открываем программу в декомпиляторе.

results = decompiler.decompileFunction(self.function, 60, self.monitor)

Декомпилируем функцию с таймаутом 60 секунд.

if not results.decompileCompleted():

Если декомпиляция не завершилась успешно, то…

print("Decompilation failed!")

… выводим сообщение об ошибке декомпиляции.

return

Прерываем выполнение метода run (задача не может продолжаться без декомпиляции).

code = results.getDecompiledFunction().getC()

Получаем декомпилированный C-подобный код функции в виде строки.

entities = re.findall(r'\b([A-Za-z_][A-Za-z0-9_]*)\b', code)

С помощью регулярного выражения находим все идентификаторы (слова, начинающиеся с буквы или подчёркивания) в коде.

filtered_names = [n for n in set(entities) if n not in self.skipped]

Создаём множество уникальных идентификаторов и исключаем те, что присутствуют в self.skipped (ключевые слова).

dialog = RenameDialog(filtered_names)

Создаем диалоговое окно RenameDialog, передавая список найденных имён для потенциального переименования.

dialog.setLocationRelativeTo(None)

Устанавливаем расположение диалога по центру экрана (None означает центр относительно родительского окна).

dialog.setVisible(True)

Делаем диалог видимым – ожидаем, пока пользователь внесёт изменения и нажмёт “Apply”.

while dialog.isVisible(): pass

Активно ждём, пока окно не будет закрыто (пользователь не закончит ввод).

success = 0

Инициализируем счётчик успешно переименованных символов.

for line in dialog.text_area.getText().split('\n'):

Перебираем каждую строку из текста, введённого пользователем в текстовой области диалога.

line = line.strip()

Удаляем пробелы в начале и конце строки.

if line and '=' in line and not line.startswith('#'):

Если строка не пуста, содержит символ “=” и не является комментарием (не начинается с “#”), то…

old, new = line.split('=', 1)

Разбиваем строку на две части по первому символу “=”, где левая часть – старое имя, правая – новое.

if self.find_and_rename(old.strip(), new.strip()):

Вызываем метод find_and_rename с очищенными от пробелов старыми и новыми именами; если переименование прошло успешно, то…

success += 1

… увеличиваем счётчик успешных переименований.

print("Successfully renamed: {}/{}".format(success, len(filtered_names)))

Выводим итоговое сообщение о том, сколько из найденных идентификаторов было успешно переименовано.

if __name__ == "__main__":

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

func = getFunctionContaining(currentAddress)

Получаем функцию, в которой находится текущий адрес курсора в Ghidra.

if func:

Если функция найдена, то…

task = AdvancedRenamer(currentProgram, func)

Создаем экземпляр задачи AdvancedRenamer, передавая текущую программу и найденную функцию.

task.run()

Запускаем выполнение задачи переименования.

else:

Если функция не найдена (курсор не находится внутри функции), то…

print("Position cursor inside function!")

… выводим сообщение с просьбой установить курсор внутри функции для корректной работы скрипта.

Подготовка.

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

Прокомментируй каждую строку и переименнуй переменные и функции нормально. Саму структуру кода оставь, как есть, не сокращая и не меняя, то есть никаких "и так далее" - пиши код полностью! Все имена должны быть подробными, то есть не tmp и прочее, никаких сокращенных бысмысленных имен. Опиши к чему пренадлежат переменные, не просто windowStruct, а UIState как напимер. Так же переименую DAT_ как g_..новоеИмя, и LABEL_куда прыгаем {НАШ_ПСЕВДО_КОД} после кода выведи все, что переименовал в формате списка старое_имя=новое_имя\n в список включай все переменные, функции, DAT_, LAB_, param_ и прочее без исключений прям все пиши

Выбираем цель, для эксперимента

Как создать скрипт-beautifier в Ghidra на Python? Программирование, Python, Гайд, Windows, Реверс, Длиннопост

В итоге, у меня получился вот такой вот список для моей функции

param_1=hWndPointer

bVar1=isCursorConfinedDueToCapture

bVar2=isMarginApplied

cVar3=isCursorCapturedResult

local_res8=clientTopLeftPoint

local_res10=clientBottomRightPoint

local_38=confinedCursorRect

local_28=windowRect

Запускаем!!

После запуска скрипта (при условии, что курсор установлен внутри функции) откроется диалоговое окно, в котором будут выведены найденные идентификаторы. Введите список переименований в формате:

ВАЖНО!!! Переменные по типу xVarN нужно сортировать по убыванию, так как они не внесены в базу. Переименование меньшей переменной приведёт к тому, что большая займёт её место, и список станет невалидным.

После ввода нажмите кнопку Apply и дождитесь окончания выполнения.

Как создать скрипт-beautifier в Ghidra на Python? Программирование, Python, Гайд, Windows, Реверс, Длиннопост

(метод подсчета требует доработки)

Как создать скрипт-beautifier в Ghidra на Python? Программирование, Python, Гайд, Windows, Реверс, Длиннопост

В итоге должно получиться нечто подобное:

Как создать скрипт-beautifier в Ghidra на Python? Программирование, Python, Гайд, Windows, Реверс, Длиннопост

Спасибо за внимание! Скачать PDF и сам скрипт можно по ссылке – https://t.me/osiechan/62 А начать путь в реверс-инжиниринге можно на увлекательном бесплатном курсе по ботостроению для ММОРПГ – https://t.me/osiechan/41

Показать полностью 4
[моё] Программирование Python Гайд Windows Реверс Длиннопост
1
Посты не найдены
О нас
О Пикабу Контакты Реклама Сообщить об ошибке Сообщить о нарушении законодательства Отзывы и предложения Новости Пикабу Мобильное приложение RSS
Информация
Помощь Кодекс Пикабу Команда Пикабу Конфиденциальность Правила соцсети О рекомендациях О компании
Наши проекты
Блоги Работа Промокоды Игры Курсы
Партнёры
Промокоды Биг Гик Промокоды Lamoda Промокоды Мвидео Промокоды Яндекс Директ Промокоды Отелло Промокоды Aroma Butik Промокоды Яндекс Путешествия Постила Футбол сегодня
На информационном ресурсе Pikabu.ru применяются рекомендательные технологии